]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Multisampling initialisation moved from vid_sdl to gl_backend. Make cubemaps array...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 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)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200
201 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"};
202
203 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"};
204
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 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"};
219
220 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."};
221
222 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)"};
223
224 extern cvar_t v_glslgamma;
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 };
681
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721 };
722
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
725 {
726         /// hash lookup data
727         struct r_glsl_permutation_s *hashnext;
728         unsigned int mode;
729         unsigned int permutation;
730
731         /// indicates if we have tried compiling this permutation already
732         qboolean compiled;
733         /// 0 if compilation failed
734         int program;
735         // texture units assigned to each detected uniform
736         int tex_Texture_First;
737         int tex_Texture_Second;
738         int tex_Texture_GammaRamps;
739         int tex_Texture_Normal;
740         int tex_Texture_Color;
741         int tex_Texture_Gloss;
742         int tex_Texture_Glow;
743         int tex_Texture_SecondaryNormal;
744         int tex_Texture_SecondaryColor;
745         int tex_Texture_SecondaryGloss;
746         int tex_Texture_SecondaryGlow;
747         int tex_Texture_Pants;
748         int tex_Texture_Shirt;
749         int tex_Texture_FogHeightTexture;
750         int tex_Texture_FogMask;
751         int tex_Texture_Lightmap;
752         int tex_Texture_Deluxemap;
753         int tex_Texture_Attenuation;
754         int tex_Texture_Cube;
755         int tex_Texture_Refraction;
756         int tex_Texture_Reflection;
757         int tex_Texture_ShadowMap2D;
758         int tex_Texture_CubeProjection;
759         int tex_Texture_ScreenDepth;
760         int tex_Texture_ScreenNormalMap;
761         int tex_Texture_ScreenDiffuse;
762         int tex_Texture_ScreenSpecular;
763         int tex_Texture_ReflectMask;
764         int tex_Texture_ReflectCube;
765         int tex_Texture_BounceGrid;
766         /// locations of detected uniforms in program object, or -1 if not found
767         int loc_Texture_First;
768         int loc_Texture_Second;
769         int loc_Texture_GammaRamps;
770         int loc_Texture_Normal;
771         int loc_Texture_Color;
772         int loc_Texture_Gloss;
773         int loc_Texture_Glow;
774         int loc_Texture_SecondaryNormal;
775         int loc_Texture_SecondaryColor;
776         int loc_Texture_SecondaryGloss;
777         int loc_Texture_SecondaryGlow;
778         int loc_Texture_Pants;
779         int loc_Texture_Shirt;
780         int loc_Texture_FogHeightTexture;
781         int loc_Texture_FogMask;
782         int loc_Texture_Lightmap;
783         int loc_Texture_Deluxemap;
784         int loc_Texture_Attenuation;
785         int loc_Texture_Cube;
786         int loc_Texture_Refraction;
787         int loc_Texture_Reflection;
788         int loc_Texture_ShadowMap2D;
789         int loc_Texture_CubeProjection;
790         int loc_Texture_ScreenDepth;
791         int loc_Texture_ScreenNormalMap;
792         int loc_Texture_ScreenDiffuse;
793         int loc_Texture_ScreenSpecular;
794         int loc_Texture_ReflectMask;
795         int loc_Texture_ReflectCube;
796         int loc_Texture_BounceGrid;
797         int loc_Alpha;
798         int loc_BloomBlur_Parameters;
799         int loc_ClientTime;
800         int loc_Color_Ambient;
801         int loc_Color_Diffuse;
802         int loc_Color_Specular;
803         int loc_Color_Glow;
804         int loc_Color_Pants;
805         int loc_Color_Shirt;
806         int loc_DeferredColor_Ambient;
807         int loc_DeferredColor_Diffuse;
808         int loc_DeferredColor_Specular;
809         int loc_DeferredMod_Diffuse;
810         int loc_DeferredMod_Specular;
811         int loc_DistortScaleRefractReflect;
812         int loc_EyePosition;
813         int loc_FogColor;
814         int loc_FogHeightFade;
815         int loc_FogPlane;
816         int loc_FogPlaneViewDist;
817         int loc_FogRangeRecip;
818         int loc_LightColor;
819         int loc_LightDir;
820         int loc_LightPosition;
821         int loc_OffsetMapping_ScaleSteps;
822         int loc_PixelSize;
823         int loc_ReflectColor;
824         int loc_ReflectFactor;
825         int loc_ReflectOffset;
826         int loc_RefractColor;
827         int loc_Saturation;
828         int loc_ScreenCenterRefractReflect;
829         int loc_ScreenScaleRefractReflect;
830         int loc_ScreenToDepth;
831         int loc_ShadowMap_Parameters;
832         int loc_ShadowMap_TextureScale;
833         int loc_SpecularPower;
834         int loc_UserVec1;
835         int loc_UserVec2;
836         int loc_UserVec3;
837         int loc_UserVec4;
838         int loc_ViewTintColor;
839         int loc_ViewToLight;
840         int loc_ModelToLight;
841         int loc_TexMatrix;
842         int loc_BackgroundTexMatrix;
843         int loc_ModelViewProjectionMatrix;
844         int loc_ModelViewMatrix;
845         int loc_PixelToScreenTexCoord;
846         int loc_ModelToReflectCube;
847         int loc_ShadowMapMatrix;
848         int loc_BloomColorSubtract;
849         int loc_NormalmapScrollBlend;
850         int loc_BounceGridMatrix;
851         int loc_BounceGridIntensity;
852 }
853 r_glsl_permutation_t;
854
855 #define SHADERPERMUTATION_HASHSIZE 256
856
857
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
860 enum
861 {
862         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
868         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 };
870 #define SHADERSTATICPARMS_COUNT 7
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
878 {
879         static int r_compileshader_staticparms_save[1];
880         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
882
883         // detect all
884         if (r_glsl_saturation_redcompensate.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886         if (r_glsl_vertextextureblend_usebothalphas.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888         if (r_shadow_glossexact.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890         if (r_glsl_postprocess.integer)
891         {
892                 if (r_glsl_postprocess_uservec1_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894                 if (r_glsl_postprocess_uservec2_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896                 if (r_glsl_postprocess_uservec3_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898                 if (r_glsl_postprocess_uservec4_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900         }
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921 }
922
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
929
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 {
932         //unsigned int hashdepth = 0;
933         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934         r_glsl_permutation_t *p;
935         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936         {
937                 if (p->mode == mode && p->permutation == permutation)
938                 {
939                         //if (hashdepth > 10)
940                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
941                         return p;
942                 }
943                 //hashdepth++;
944         }
945         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946         p->mode = mode;
947         p->permutation = permutation;
948         p->hashnext = r_glsl_permutationhash[mode][hashindex];
949         r_glsl_permutationhash[mode][hashindex] = p;
950         //if (hashdepth > 10)
951         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
952         return p;
953 }
954
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
956 {
957         char *shaderstring;
958         if (!filename || !filename[0])
959                 return NULL;
960         if (!strcmp(filename, "glsl/default.glsl"))
961         {
962                 if (!glslshaderstring)
963                 {
964                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965                         if (glslshaderstring)
966                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
967                         else
968                                 glslshaderstring = (char *)builtinshaderstring;
969                 }
970                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
972                 return shaderstring;
973         }
974         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
975         if (shaderstring)
976         {
977                 if (printfromdisknotice)
978                         Con_DPrintf("from disk %s... ", filename);
979                 return shaderstring;
980         }
981         return shaderstring;
982 }
983
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
985 {
986         int i;
987         int sampler;
988         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989         char *vertexstring, *geometrystring, *fragmentstring;
990         char permutationname[256];
991         int vertstrings_count = 0;
992         int geomstrings_count = 0;
993         int fragstrings_count = 0;
994         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997
998         if (p->compiled)
999                 return;
1000         p->compiled = true;
1001         p->program = 0;
1002
1003         permutationname[0] = 0;
1004         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007
1008         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009
1010         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011         if(vid.support.gl20shaders130)
1012         {
1013                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1019         }
1020
1021         // the first pretext is which type of shader to compile as
1022         // (later these will all be bound together as a program object)
1023         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026
1027         // the second pretext is the mode (for example a light source)
1028         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032
1033         // now add all the permutation pretexts
1034         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035         {
1036                 if (permutation & (1<<i))
1037                 {
1038                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1042                 }
1043                 else
1044                 {
1045                         // keep line numbers correct
1046                         vertstrings_list[vertstrings_count++] = "\n";
1047                         geomstrings_list[geomstrings_count++] = "\n";
1048                         fragstrings_list[fragstrings_count++] = "\n";
1049                 }
1050         }
1051
1052         // add static parms
1053         R_CompileShader_AddStaticParms(mode, permutation);
1054         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055         vertstrings_count += shaderstaticparms_count;
1056         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057         geomstrings_count += shaderstaticparms_count;
1058         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         fragstrings_count += shaderstaticparms_count;
1060
1061         // now append the shader text itself
1062         vertstrings_list[vertstrings_count++] = vertexstring;
1063         geomstrings_list[geomstrings_count++] = geometrystring;
1064         fragstrings_list[fragstrings_count++] = fragmentstring;
1065
1066         // if any sources were NULL, clear the respective list
1067         if (!vertexstring)
1068                 vertstrings_count = 0;
1069         if (!geometrystring)
1070                 geomstrings_count = 0;
1071         if (!fragmentstring)
1072                 fragstrings_count = 0;
1073
1074         // compile the shader program
1075         if (vertstrings_count + geomstrings_count + fragstrings_count)
1076                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1077         if (p->program)
1078         {
1079                 CHECKGLERROR
1080                 qglUseProgram(p->program);CHECKGLERROR
1081                 // look up all the uniform variable names we care about, so we don't
1082                 // have to look them up every time we set them
1083
1084                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1085                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1086                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1088                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1089                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1090                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1091                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1096                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1097                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1099                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1103                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1104                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1105                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1115                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1117                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1118                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1119                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1120                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1121                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1122                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1123                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1130                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1131                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1132                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1133                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1135                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1136                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1137                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1138                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1140                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1141                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1142                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1143                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1144                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1145                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1148                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1151                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1152                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1153                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1154                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1155                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1156                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1157                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1158                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1159                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169                 // initialize the samplers to refer to the texture units we use
1170                 p->tex_Texture_First = -1;
1171                 p->tex_Texture_Second = -1;
1172                 p->tex_Texture_GammaRamps = -1;
1173                 p->tex_Texture_Normal = -1;
1174                 p->tex_Texture_Color = -1;
1175                 p->tex_Texture_Gloss = -1;
1176                 p->tex_Texture_Glow = -1;
1177                 p->tex_Texture_SecondaryNormal = -1;
1178                 p->tex_Texture_SecondaryColor = -1;
1179                 p->tex_Texture_SecondaryGloss = -1;
1180                 p->tex_Texture_SecondaryGlow = -1;
1181                 p->tex_Texture_Pants = -1;
1182                 p->tex_Texture_Shirt = -1;
1183                 p->tex_Texture_FogHeightTexture = -1;
1184                 p->tex_Texture_FogMask = -1;
1185                 p->tex_Texture_Lightmap = -1;
1186                 p->tex_Texture_Deluxemap = -1;
1187                 p->tex_Texture_Attenuation = -1;
1188                 p->tex_Texture_Cube = -1;
1189                 p->tex_Texture_Refraction = -1;
1190                 p->tex_Texture_Reflection = -1;
1191                 p->tex_Texture_ShadowMap2D = -1;
1192                 p->tex_Texture_CubeProjection = -1;
1193                 p->tex_Texture_ScreenDepth = -1;
1194                 p->tex_Texture_ScreenNormalMap = -1;
1195                 p->tex_Texture_ScreenDiffuse = -1;
1196                 p->tex_Texture_ScreenSpecular = -1;
1197                 p->tex_Texture_ReflectMask = -1;
1198                 p->tex_Texture_ReflectCube = -1;
1199                 p->tex_Texture_BounceGrid = -1;
1200                 sampler = 0;
1201                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1202                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1203                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1204                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1205                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1206                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1207                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1212                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1213                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1214                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1216                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1217                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1218                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1219                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1220                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1221                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1222                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1223                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1229                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1230                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1231                 CHECKGLERROR
1232                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1233         }
1234         else
1235                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1236
1237         // free the strings
1238         if (vertexstring)
1239                 Mem_Free(vertexstring);
1240         if (geometrystring)
1241                 Mem_Free(geometrystring);
1242         if (fragmentstring)
1243                 Mem_Free(fragmentstring);
1244 }
1245
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 {
1248         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249         if (r_glsl_permutation != perm)
1250         {
1251                 r_glsl_permutation = perm;
1252                 if (!r_glsl_permutation->program)
1253                 {
1254                         if (!r_glsl_permutation->compiled)
1255                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1256                         if (!r_glsl_permutation->program)
1257                         {
1258                                 // remove features until we find a valid permutation
1259                                 int i;
1260                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261                                 {
1262                                         // reduce i more quickly whenever it would not remove any bits
1263                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264                                         if (!(permutation & j))
1265                                                 continue;
1266                                         permutation -= j;
1267                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268                                         if (!r_glsl_permutation->compiled)
1269                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                                         if (r_glsl_permutation->program)
1271                                                 break;
1272                                 }
1273                                 if (i >= SHADERPERMUTATION_COUNT)
1274                                 {
1275                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277                                         qglUseProgram(0);CHECKGLERROR
1278                                         return; // no bit left to clear, entire mode is broken
1279                                 }
1280                         }
1281                 }
1282                 CHECKGLERROR
1283                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284         }
1285         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1288 }
1289
1290 #ifdef SUPPORTD3D
1291
1292 #ifdef SUPPORTD3D
1293 #include <d3d9.h>
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1296 #endif
1297
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1300 {
1301         /// hash lookup data
1302         struct r_hlsl_permutation_s *hashnext;
1303         unsigned int mode;
1304         unsigned int permutation;
1305
1306         /// indicates if we have tried compiling this permutation already
1307         qboolean compiled;
1308         /// NULL if compilation failed
1309         IDirect3DVertexShader9 *vertexshader;
1310         IDirect3DPixelShader9 *pixelshader;
1311 }
1312 r_hlsl_permutation_t;
1313
1314 typedef enum D3DVSREGISTER_e
1315 {
1316         D3DVSREGISTER_TexMatrix = 0, // float4x4
1317         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321         D3DVSREGISTER_ModelToLight = 20, // float4x4
1322         D3DVSREGISTER_EyePosition = 24,
1323         D3DVSREGISTER_FogPlane = 25,
1324         D3DVSREGISTER_LightDir = 26,
1325         D3DVSREGISTER_LightPosition = 27,
1326 }
1327 D3DVSREGISTER_t;
1328
1329 typedef enum D3DPSREGISTER_e
1330 {
1331         D3DPSREGISTER_Alpha = 0,
1332         D3DPSREGISTER_BloomBlur_Parameters = 1,
1333         D3DPSREGISTER_ClientTime = 2,
1334         D3DPSREGISTER_Color_Ambient = 3,
1335         D3DPSREGISTER_Color_Diffuse = 4,
1336         D3DPSREGISTER_Color_Specular = 5,
1337         D3DPSREGISTER_Color_Glow = 6,
1338         D3DPSREGISTER_Color_Pants = 7,
1339         D3DPSREGISTER_Color_Shirt = 8,
1340         D3DPSREGISTER_DeferredColor_Ambient = 9,
1341         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342         D3DPSREGISTER_DeferredColor_Specular = 11,
1343         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344         D3DPSREGISTER_DeferredMod_Specular = 13,
1345         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346         D3DPSREGISTER_EyePosition = 15, // unused
1347         D3DPSREGISTER_FogColor = 16,
1348         D3DPSREGISTER_FogHeightFade = 17,
1349         D3DPSREGISTER_FogPlane = 18,
1350         D3DPSREGISTER_FogPlaneViewDist = 19,
1351         D3DPSREGISTER_FogRangeRecip = 20,
1352         D3DPSREGISTER_LightColor = 21,
1353         D3DPSREGISTER_LightDir = 22, // unused
1354         D3DPSREGISTER_LightPosition = 23,
1355         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356         D3DPSREGISTER_PixelSize = 25,
1357         D3DPSREGISTER_ReflectColor = 26,
1358         D3DPSREGISTER_ReflectFactor = 27,
1359         D3DPSREGISTER_ReflectOffset = 28,
1360         D3DPSREGISTER_RefractColor = 29,
1361         D3DPSREGISTER_Saturation = 30,
1362         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364         D3DPSREGISTER_ScreenToDepth = 33,
1365         D3DPSREGISTER_ShadowMap_Parameters = 34,
1366         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367         D3DPSREGISTER_SpecularPower = 36,
1368         D3DPSREGISTER_UserVec1 = 37,
1369         D3DPSREGISTER_UserVec2 = 38,
1370         D3DPSREGISTER_UserVec3 = 39,
1371         D3DPSREGISTER_UserVec4 = 40,
1372         D3DPSREGISTER_ViewTintColor = 41,
1373         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374         D3DPSREGISTER_BloomColorSubtract = 43,
1375         D3DPSREGISTER_ViewToLight = 44, // float4x4
1376         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377         D3DPSREGISTER_NormalmapScrollBlend = 52,
1378         // next at 53
1379 }
1380 D3DPSREGISTER_t;
1381
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1388
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 {
1391         //unsigned int hashdepth = 0;
1392         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393         r_hlsl_permutation_t *p;
1394         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395         {
1396                 if (p->mode == mode && p->permutation == permutation)
1397                 {
1398                         //if (hashdepth > 10)
1399                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1400                         return p;
1401                 }
1402                 //hashdepth++;
1403         }
1404         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405         p->mode = mode;
1406         p->permutation = permutation;
1407         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408         r_hlsl_permutationhash[mode][hashindex] = p;
1409         //if (hashdepth > 10)
1410         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1411         return p;
1412 }
1413
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1415 {
1416         char *shaderstring;
1417         if (!filename || !filename[0])
1418                 return NULL;
1419         if (!strcmp(filename, "hlsl/default.hlsl"))
1420         {
1421                 if (!hlslshaderstring)
1422                 {
1423                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424                         if (hlslshaderstring)
1425                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426                         else
1427                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1428                 }
1429                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431                 return shaderstring;
1432         }
1433         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1434         if (shaderstring)
1435         {
1436                 if (printfromdisknotice)
1437                         Con_DPrintf("from disk %s... ", filename);
1438                 return shaderstring;
1439         }
1440         return shaderstring;
1441 }
1442
1443 #include <d3dx9.h>
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1446
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 {
1449         DWORD *vsbin = NULL;
1450         DWORD *psbin = NULL;
1451         fs_offset_t vsbinsize;
1452         fs_offset_t psbinsize;
1453 //      IDirect3DVertexShader9 *vs = NULL;
1454 //      IDirect3DPixelShader9 *ps = NULL;
1455         ID3DXBuffer *vslog = NULL;
1456         ID3DXBuffer *vsbuffer = NULL;
1457         ID3DXConstantTable *vsconstanttable = NULL;
1458         ID3DXBuffer *pslog = NULL;
1459         ID3DXBuffer *psbuffer = NULL;
1460         ID3DXConstantTable *psconstanttable = NULL;
1461         int vsresult = 0;
1462         int psresult = 0;
1463         char temp[MAX_INPUTLINE];
1464         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465         qboolean debugshader = gl_paranoid.integer != 0;
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468         if (!debugshader)
1469         {
1470                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472         }
1473         if ((!vsbin && vertstring) || (!psbin && fragstring))
1474         {
1475                 const char* dllnames_d3dx9 [] =
1476                 {
1477                         "d3dx9_43.dll",
1478                         "d3dx9_42.dll",
1479                         "d3dx9_41.dll",
1480                         "d3dx9_40.dll",
1481                         "d3dx9_39.dll",
1482                         "d3dx9_38.dll",
1483                         "d3dx9_37.dll",
1484                         "d3dx9_36.dll",
1485                         "d3dx9_35.dll",
1486                         "d3dx9_34.dll",
1487                         "d3dx9_33.dll",
1488                         "d3dx9_32.dll",
1489                         "d3dx9_31.dll",
1490                         "d3dx9_30.dll",
1491                         "d3dx9_29.dll",
1492                         "d3dx9_28.dll",
1493                         "d3dx9_27.dll",
1494                         "d3dx9_26.dll",
1495                         "d3dx9_25.dll",
1496                         "d3dx9_24.dll",
1497                         NULL
1498                 };
1499                 dllhandle_t d3dx9_dll = NULL;
1500                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503                 dllfunction_t d3dx9_dllfuncs[] =
1504                 {
1505                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1506                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1507                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1508                         {NULL, NULL}
1509                 };
1510                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511                 {
1512                         DWORD shaderflags = 0;
1513                         if (debugshader)
1514                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517                         if (vertstring && vertstring[0])
1518                         {
1519                                 if (debugshader)
1520                                 {
1521 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1525                                 }
1526                                 else
1527                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528                                 if (vsbuffer)
1529                                 {
1530                                         vsbinsize = vsbuffer->GetBufferSize();
1531                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533                                         vsbuffer->Release();
1534                                 }
1535                                 if (vslog)
1536                                 {
1537                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1539                                         vslog->Release();
1540                                 }
1541                         }
1542                         if (fragstring && fragstring[0])
1543                         {
1544                                 if (debugshader)
1545                                 {
1546 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1550                                 }
1551                                 else
1552                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553                                 if (psbuffer)
1554                                 {
1555                                         psbinsize = psbuffer->GetBufferSize();
1556                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558                                         psbuffer->Release();
1559                                 }
1560                                 if (pslog)
1561                                 {
1562                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1564                                         pslog->Release();
1565                                 }
1566                         }
1567                         Sys_UnloadLibrary(&d3dx9_dll);
1568                 }
1569                 else
1570                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1571         }
1572         if (vsbin && psbin)
1573         {
1574                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575                 if (FAILED(vsresult))
1576                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578                 if (FAILED(psresult))
1579                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580         }
1581         // free the shader data
1582         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1584 }
1585
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1587 {
1588         int i;
1589         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590         int vertstring_length = 0;
1591         int geomstring_length = 0;
1592         int fragstring_length = 0;
1593         char *t;
1594         char *vertexstring, *geometrystring, *fragmentstring;
1595         char *vertstring, *geomstring, *fragstring;
1596         char permutationname[256];
1597         char cachename[256];
1598         int vertstrings_count = 0;
1599         int geomstrings_count = 0;
1600         int fragstrings_count = 0;
1601         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604
1605         if (p->compiled)
1606                 return;
1607         p->compiled = true;
1608         p->vertexshader = NULL;
1609         p->pixelshader = NULL;
1610
1611         permutationname[0] = 0;
1612         cachename[0] = 0;
1613         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616
1617         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618         strlcat(cachename, "hlsl/", sizeof(cachename));
1619
1620         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621         vertstrings_count = 0;
1622         geomstrings_count = 0;
1623         fragstrings_count = 0;
1624         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627
1628         // the first pretext is which type of shader to compile as
1629         // (later these will all be bound together as a program object)
1630         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633
1634         // the second pretext is the mode (for example a light source)
1635         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639         strlcat(cachename, modeinfo->name, sizeof(cachename));
1640
1641         // now add all the permutation pretexts
1642         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643         {
1644                 if (permutation & (1<<i))
1645                 {
1646                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1651                 }
1652                 else
1653                 {
1654                         // keep line numbers correct
1655                         vertstrings_list[vertstrings_count++] = "\n";
1656                         geomstrings_list[geomstrings_count++] = "\n";
1657                         fragstrings_list[fragstrings_count++] = "\n";
1658                 }
1659         }
1660
1661         // add static parms
1662         R_CompileShader_AddStaticParms(mode, permutation);
1663         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664         vertstrings_count += shaderstaticparms_count;
1665         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666         geomstrings_count += shaderstaticparms_count;
1667         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         fragstrings_count += shaderstaticparms_count;
1669
1670         // replace spaces in the cachename with _ characters
1671         for (i = 0;cachename[i];i++)
1672                 if (cachename[i] == ' ')
1673                         cachename[i] = '_';
1674
1675         // now append the shader text itself
1676         vertstrings_list[vertstrings_count++] = vertexstring;
1677         geomstrings_list[geomstrings_count++] = geometrystring;
1678         fragstrings_list[fragstrings_count++] = fragmentstring;
1679
1680         // if any sources were NULL, clear the respective list
1681         if (!vertexstring)
1682                 vertstrings_count = 0;
1683         if (!geometrystring)
1684                 geomstrings_count = 0;
1685         if (!fragmentstring)
1686                 fragstrings_count = 0;
1687
1688         vertstring_length = 0;
1689         for (i = 0;i < vertstrings_count;i++)
1690                 vertstring_length += strlen(vertstrings_list[i]);
1691         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694
1695         geomstring_length = 0;
1696         for (i = 0;i < geomstrings_count;i++)
1697                 geomstring_length += strlen(geomstrings_list[i]);
1698         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701
1702         fragstring_length = 0;
1703         for (i = 0;i < fragstrings_count;i++)
1704                 fragstring_length += strlen(fragstrings_list[i]);
1705         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708
1709         // try to load the cached shader, or generate one
1710         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711
1712         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714         else
1715                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1716
1717         // free the strings
1718         if (vertstring)
1719                 Mem_Free(vertstring);
1720         if (geomstring)
1721                 Mem_Free(geomstring);
1722         if (fragstring)
1723                 Mem_Free(fragstring);
1724         if (vertexstring)
1725                 Mem_Free(vertexstring);
1726         if (geometrystring)
1727                 Mem_Free(geometrystring);
1728         if (fragmentstring)
1729                 Mem_Free(fragmentstring);
1730 }
1731
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1745
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 {
1748         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749         if (r_hlsl_permutation != perm)
1750         {
1751                 r_hlsl_permutation = perm;
1752                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753                 {
1754                         if (!r_hlsl_permutation->compiled)
1755                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1756                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757                         {
1758                                 // remove features until we find a valid permutation
1759                                 int i;
1760                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761                                 {
1762                                         // reduce i more quickly whenever it would not remove any bits
1763                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764                                         if (!(permutation & j))
1765                                                 continue;
1766                                         permutation -= j;
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         if (!r_hlsl_permutation->compiled)
1769                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1770                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1771                                                 break;
1772                                 }
1773                                 if (i >= SHADERPERMUTATION_COUNT)
1774                                 {
1775                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777                                         return; // no bit left to clear, entire mode is broken
1778                                 }
1779                         }
1780                 }
1781                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783         }
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1787 }
1788 #endif
1789
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 {
1792         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1796 }
1797
1798 void R_GLSL_Restart_f(void)
1799 {
1800         unsigned int i, limit;
1801         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802                 Mem_Free(glslshaderstring);
1803         glslshaderstring = NULL;
1804         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805                 Mem_Free(hlslshaderstring);
1806         hlslshaderstring = NULL;
1807         switch(vid.renderpath)
1808         {
1809         case RENDERPATH_D3D9:
1810 #ifdef SUPPORTD3D
1811                 {
1812                         r_hlsl_permutation_t *p;
1813                         r_hlsl_permutation = NULL;
1814                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815                         for (i = 0;i < limit;i++)
1816                         {
1817                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818                                 {
1819                                         if (p->vertexshader)
1820                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1821                                         if (p->pixelshader)
1822                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1823                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1824                                 }
1825                         }
1826                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1827                 }
1828 #endif
1829                 break;
1830         case RENDERPATH_D3D10:
1831                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832                 break;
1833         case RENDERPATH_D3D11:
1834                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                 break;
1836         case RENDERPATH_GL20:
1837         case RENDERPATH_GLES2:
1838                 {
1839                         r_glsl_permutation_t *p;
1840                         r_glsl_permutation = NULL;
1841                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842                         for (i = 0;i < limit;i++)
1843                         {
1844                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845                                 {
1846                                         GL_Backend_FreeProgram(p->program);
1847                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1848                                 }
1849                         }
1850                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1851                 }
1852                 break;
1853         case RENDERPATH_GL11:
1854         case RENDERPATH_GL13:
1855         case RENDERPATH_GLES1:
1856                 break;
1857         case RENDERPATH_SOFT:
1858                 break;
1859         }
1860 }
1861
1862 void R_GLSL_DumpShader_f(void)
1863 {
1864         int i;
1865         qfile_t *file;
1866
1867         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868         if (file)
1869         {
1870                 FS_Print(file, "/* The engine may define the following macros:\n");
1871                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872                 for (i = 0;i < SHADERMODE_COUNT;i++)
1873                         FS_Print(file, glslshadermodeinfo[i].pretext);
1874                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875                         FS_Print(file, shaderpermutationinfo[i].pretext);
1876                 FS_Print(file, "*/\n");
1877                 FS_Print(file, builtinshaderstring);
1878                 FS_Close(file);
1879                 Con_Printf("glsl/default.glsl written\n");
1880         }
1881         else
1882                 Con_Printf("failed to write to glsl/default.glsl\n");
1883
1884         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinhlslshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("hlsl/default.hlsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 }
1901
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 {
1904         if (!second)
1905                 texturemode = GL_MODULATE;
1906         switch (vid.renderpath)
1907         {
1908         case RENDERPATH_D3D9:
1909 #ifdef SUPPORTD3D
1910                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1911                 R_Mesh_TexBind(GL20TU_FIRST , first );
1912                 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1924                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1926                 break;
1927         case RENDERPATH_GL13:
1928         case RENDERPATH_GLES1:
1929                 R_Mesh_TexBind(0, first );
1930                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931                 R_Mesh_TexBind(1, second);
1932                 if (second)
1933                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934                 break;
1935         case RENDERPATH_GL11:
1936                 R_Mesh_TexBind(0, first );
1937                 break;
1938         case RENDERPATH_SOFT:
1939                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1940                 R_Mesh_TexBind(GL20TU_FIRST , first );
1941                 R_Mesh_TexBind(GL20TU_SECOND, second);
1942                 break;
1943         }
1944 }
1945
1946 void R_SetupShader_DepthOrShadow(void)
1947 {
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964                 break;
1965         case RENDERPATH_GL13:
1966         case RENDERPATH_GLES1:
1967                 R_Mesh_TexBind(0, 0);
1968                 R_Mesh_TexBind(1, 0);
1969                 break;
1970         case RENDERPATH_GL11:
1971                 R_Mesh_TexBind(0, 0);
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975                 break;
1976         }
1977 }
1978
1979 void R_SetupShader_ShowDepth(void)
1980 {
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTHLSL
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1986 #endif
1987                 break;
1988         case RENDERPATH_D3D10:
1989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                 break;
1991         case RENDERPATH_D3D11:
1992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_GL20:
1995         case RENDERPATH_GLES2:
1996                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997                 break;
1998         case RENDERPATH_GL13:
1999         case RENDERPATH_GLES1:
2000                 break;
2001         case RENDERPATH_GL11:
2002                 break;
2003         case RENDERPATH_SOFT:
2004                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2005                 break;
2006         }
2007 }
2008
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2033
2034 #define BLENDFUNC_ALLOWS_COLORMOD      1
2035 #define BLENDFUNC_ALLOWS_FOG           2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2040 {
2041         int r = 0;
2042
2043         // a blendfunc allows colormod if:
2044         // a) it can never keep the destination pixel invariant, or
2045         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046         // this is to prevent unintended side effects from colormod
2047
2048         // a blendfunc allows fog if:
2049         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050         // this is to prevent unintended side effects from fog
2051
2052         // these checks are the output of fogeval.pl
2053
2054         r |= BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076
2077         return r;
2078 }
2079
2080 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)
2081 {
2082         // select a permutation of the lighting shader appropriate to this
2083         // combination of texture, entity, light source, and fogging, only use the
2084         // minimum features necessary to avoid wasting rendering time in the
2085         // fragment shader on features that are not being used
2086         unsigned int permutation = 0;
2087         unsigned int mode = 0;
2088         int blendfuncflags;
2089         static float dummy_colormod[3] = {1, 1, 1};
2090         float *colormod = rsurface.colormod;
2091         float m16f[16];
2092         matrix4x4_t tempmatrix;
2093         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2097                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2098         if (rsurfacepass == RSURFPASS_BACKGROUND)
2099         {
2100                 // distorted background
2101                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2102                 {
2103                         mode = SHADERMODE_WATER;
2104                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2105                         {
2106                                 // this is the right thing to do for wateralpha
2107                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2108                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2109                         }
2110                         else
2111                         {
2112                                 // this is the right thing to do for entity alpha
2113                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115                         }
2116                 }
2117                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2118                 {
2119                         mode = SHADERMODE_REFRACTION;
2120                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122                 }
2123                 else
2124                 {
2125                         mode = SHADERMODE_GENERIC;
2126                         permutation |= SHADERPERMUTATION_DIFFUSE;
2127                         GL_BlendFunc(GL_ONE, GL_ZERO);
2128                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2129                 }
2130         }
2131         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2132         {
2133                 if (r_glsl_offsetmapping.integer)
2134                 {
2135                         switch(rsurface.texture->offsetmapping)
2136                         {
2137                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2138                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140                         case OFFSETMAPPING_OFF: break;
2141                         }
2142                 }
2143                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145                 // normalmap (deferred prepass), may use alpha test on diffuse
2146                 mode = SHADERMODE_DEFERREDGEOMETRY;
2147                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149         }
2150         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151         {
2152                 if (r_glsl_offsetmapping.integer)
2153                 {
2154                         switch(rsurface.texture->offsetmapping)
2155                         {
2156                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2157                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159                         case OFFSETMAPPING_OFF: break;
2160                         }
2161                 }
2162                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2163                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2164                 // light source
2165                 mode = SHADERMODE_LIGHTSOURCE;
2166                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2167                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2168                 if (diffusescale > 0)
2169                         permutation |= SHADERPERMUTATION_DIFFUSE;
2170                 if (specularscale > 0)
2171                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2172                 if (r_refdef.fogenabled)
2173                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2174                 if (rsurface.texture->colormapping)
2175                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2176                 if (r_shadow_usingshadowmap2d)
2177                 {
2178                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2179                         if(r_shadow_shadowmapvsdct)
2180                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181
2182                         if (r_shadow_shadowmapsampler)
2183                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2184                         if (r_shadow_shadowmappcf > 1)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2186                         else if (r_shadow_shadowmappcf)
2187                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188                 }
2189                 if (rsurface.texture->reflectmasktexture)
2190                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2191                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2192                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193         }
2194         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195         {
2196                 if (r_glsl_offsetmapping.integer)
2197                 {
2198                         switch(rsurface.texture->offsetmapping)
2199                         {
2200                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203                         case OFFSETMAPPING_OFF: break;
2204                         }
2205                 }
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208                 // unshaded geometry (fullbright or ambient model lighting)
2209                 mode = SHADERMODE_FLATCOLOR;
2210                 ambientscale = diffusescale = specularscale = 0;
2211                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2212                         permutation |= SHADERPERMUTATION_GLOW;
2213                 if (r_refdef.fogenabled)
2214                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2215                 if (rsurface.texture->colormapping)
2216                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2217                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2218                 {
2219                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2220                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221
2222                         if (r_shadow_shadowmapsampler)
2223                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2224                         if (r_shadow_shadowmappcf > 1)
2225                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2226                         else if (r_shadow_shadowmappcf)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2228                 }
2229                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2230                         permutation |= SHADERPERMUTATION_REFLECTION;
2231                 if (rsurface.texture->reflectmasktexture)
2232                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235         }
2236         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2237         {
2238                 if (r_glsl_offsetmapping.integer)
2239                 {
2240                         switch(rsurface.texture->offsetmapping)
2241                         {
2242                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2243                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245                         case OFFSETMAPPING_OFF: break;
2246                         }
2247                 }
2248                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250                 // directional model lighting
2251                 mode = SHADERMODE_LIGHTDIRECTION;
2252                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2253                         permutation |= SHADERPERMUTATION_GLOW;
2254                 permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265
2266                         if (r_shadow_shadowmapsampler)
2267                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268                         if (r_shadow_shadowmappcf > 1)
2269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270                         else if (r_shadow_shadowmappcf)
2271                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274                         permutation |= SHADERPERMUTATION_REFLECTION;
2275                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2276                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2277                 if (rsurface.texture->reflectmasktexture)
2278                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279                 if (r_shadow_bouncegridtexture)
2280                 {
2281                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2282                         if (r_shadow_bouncegriddirectional)
2283                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2284                 }
2285                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287         }
2288         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2289         {
2290                 if (r_glsl_offsetmapping.integer)
2291                 {
2292                         switch(rsurface.texture->offsetmapping)
2293                         {
2294                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_OFF: break;
2298                         }
2299                 }
2300                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302                 // ambient model lighting
2303                 mode = SHADERMODE_LIGHTDIRECTION;
2304                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2305                         permutation |= SHADERPERMUTATION_GLOW;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmapsampler)
2316                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317                         if (r_shadow_shadowmappcf > 1)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319                         else if (r_shadow_shadowmappcf)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336         }
2337         else
2338         {
2339                 if (r_glsl_offsetmapping.integer)
2340                 {
2341                         switch(rsurface.texture->offsetmapping)
2342                         {
2343                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2344                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346                         case OFFSETMAPPING_OFF: break;
2347                         }
2348                 }
2349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2351                 // lightmapped wall
2352                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353                         permutation |= SHADERPERMUTATION_GLOW;
2354                 if (r_refdef.fogenabled)
2355                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356                 if (rsurface.texture->colormapping)
2357                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2358                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359                 {
2360                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362
2363                         if (r_shadow_shadowmapsampler)
2364                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365                         if (r_shadow_shadowmappcf > 1)
2366                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367                         else if (r_shadow_shadowmappcf)
2368                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2369                 }
2370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371                         permutation |= SHADERPERMUTATION_REFLECTION;
2372                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374                 if (rsurface.texture->reflectmasktexture)
2375                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376                 if (FAKELIGHT_ENABLED)
2377                 {
2378                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379                         mode = SHADERMODE_FAKELIGHT;
2380                         permutation |= SHADERPERMUTATION_DIFFUSE;
2381                         if (specularscale > 0)
2382                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383                 }
2384                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2385                 {
2386                         // deluxemapping (light direction texture)
2387                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2389                         else
2390                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391                         permutation |= SHADERPERMUTATION_DIFFUSE;
2392                         if (specularscale > 0)
2393                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394                 }
2395                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2396                 {
2397                         // fake deluxemapping (uniform light direction in tangentspace)
2398                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399                         permutation |= SHADERPERMUTATION_DIFFUSE;
2400                         if (specularscale > 0)
2401                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402                 }
2403                 else if (rsurface.uselightmaptexture)
2404                 {
2405                         // ordinary lightmapping (q1bsp, q3bsp)
2406                         mode = SHADERMODE_LIGHTMAP;
2407                 }
2408                 else
2409                 {
2410                         // ordinary vertex coloring (q3bsp)
2411                         mode = SHADERMODE_VERTEXCOLOR;
2412                 }
2413                 if (r_shadow_bouncegridtexture)
2414                 {
2415                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416                         if (r_shadow_bouncegriddirectional)
2417                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418                 }
2419                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421         }
2422         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423                 colormod = dummy_colormod;
2424         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428         switch(vid.renderpath)
2429         {
2430         case RENDERPATH_D3D9:
2431 #ifdef SUPPORTD3D
2432                 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);
2433                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436                 if (mode == SHADERMODE_LIGHTSOURCE)
2437                 {
2438                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2440                 }
2441                 else
2442                 {
2443                         if (mode == SHADERMODE_LIGHTDIRECTION)
2444                         {
2445                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2446                         }
2447                 }
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2453
2454                 if (mode == SHADERMODE_LIGHTSOURCE)
2455                 {
2456                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2461
2462                         // additive passes are only darkened by fog, not tinted
2463                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2465                 }
2466                 else
2467                 {
2468                         if (mode == SHADERMODE_FLATCOLOR)
2469                         {
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2471                         }
2472                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2473                         {
2474                                 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]);
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476                                 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);
2477                                 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);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2481                         }
2482                         else
2483                         {
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486                                 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);
2487                                 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);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2489                         }
2490                         // additive passes are only darkened by fog, not tinted
2491                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2493                         else
2494                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495                         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);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503                         if (mode == SHADERMODE_WATER)
2504                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2505                 }
2506                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509                 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));
2510                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511                 if (rsurface.texture->pantstexture)
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2513                 else
2514                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515                 if (rsurface.texture->shirttexture)
2516                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2517                 else
2518                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2524                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2525                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2528                         );
2529                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2530                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2531
2532                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2533                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2534                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2535                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2536                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2538                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2539                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2540                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2541                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2542                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2543                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2544                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2545                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2546                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2547                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2548                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2549                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2550                 {
2551                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2552                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2553                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2554                 }
2555                 else
2556                 {
2557                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2558                 }
2559 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2560 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2561                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2562                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2563                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2564                 {
2565                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2566                         if (rsurface.rtlight)
2567                         {
2568                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2569                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2570                         }
2571                 }
2572 #endif
2573                 break;
2574         case RENDERPATH_D3D10:
2575                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576                 break;
2577         case RENDERPATH_D3D11:
2578                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2579                 break;
2580         case RENDERPATH_GL20:
2581         case RENDERPATH_GLES2:
2582                 if (!vid.useinterleavedarrays)
2583                 {
2584                         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);
2585                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2586                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2591                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2592                 }
2593                 else
2594                 {
2595                         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);
2596                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2597                 }
2598                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2599                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2600                 if (mode == SHADERMODE_LIGHTSOURCE)
2601                 {
2602                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2603                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2604                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2605                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2606                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607                         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);
2608         
2609                         // additive passes are only darkened by fog, not tinted
2610                         if (r_glsl_permutation->loc_FogColor >= 0)
2611                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2612                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2613                 }
2614                 else
2615                 {
2616                         if (mode == SHADERMODE_FLATCOLOR)
2617                         {
2618                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2619                         }
2620                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2621                         {
2622                                 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]);
2623                                 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]);
2624                                 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);
2625                                 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);
2626                                 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);
2627                                 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]);
2628                                 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]);
2629                         }
2630                         else
2631                         {
2632                                 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]);
2633                                 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]);
2634                                 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);
2635                                 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);
2636                                 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);
2637                         }
2638                         // additive passes are only darkened by fog, not tinted
2639                         if (r_glsl_permutation->loc_FogColor >= 0)
2640                         {
2641                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2642                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2643                                 else
2644                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2645                         }
2646                         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);
2647                         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]);
2648                         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]);
2649                         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]);
2650                         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]);
2651                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2652                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2653                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2654                         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]);
2655                 }
2656                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2657                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2658                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2659                 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]);
2660                 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]);
2661
2662                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2663                 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));
2664                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2665                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2666                 {
2667                         if (rsurface.texture->pantstexture)
2668                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2669                         else
2670                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2671                 }
2672                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2673                 {
2674                         if (rsurface.texture->shirttexture)
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2676                         else
2677                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2678                 }
2679                 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]);
2680                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2682                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2683                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2684                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688                         );
2689                 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]);
2690                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2691                 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);}
2692                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2693
2694                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2695                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2697                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2698                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2700                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2701                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2705                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2706                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2707                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2708                 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);
2709                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2710                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2711                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2712                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2713                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2714                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2715                 {
2716                         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);
2717                         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);
2718                         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);
2719                 }
2720                 else
2721                 {
2722                         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);
2723                 }
2724                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2725                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2726                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2727                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2728                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2729                 {
2730                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2731                         if (rsurface.rtlight)
2732                         {
2733                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2734                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2735                         }
2736                 }
2737                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2738                 CHECKGLERROR
2739                 break;
2740         case RENDERPATH_GL11:
2741         case RENDERPATH_GL13:
2742         case RENDERPATH_GLES1:
2743                 break;
2744         case RENDERPATH_SOFT:
2745                 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);
2746                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747                 R_SetupShader_SetPermutationSoft(mode, permutation);
2748                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749                 if (mode == SHADERMODE_LIGHTSOURCE)
2750                 {
2751                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757         
2758                         // additive passes are only darkened by fog, not tinted
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761                 }
2762                 else
2763                 {
2764                         if (mode == SHADERMODE_FLATCOLOR)
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767                         }
2768                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2769                         {
2770                                 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]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772                                 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);
2773                                 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);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777                         }
2778                         else
2779                         {
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782                                 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);
2783                                 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);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785                         }
2786                         // additive passes are only darkened by fog, not tinted
2787                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789                         else
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791                         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);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794                         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]);
2795                         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]);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800                 }
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805                 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]);
2806
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808                 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));
2809                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811                 {
2812                         if (rsurface.texture->pantstexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816                 }
2817                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818                 {
2819                         if (rsurface.texture->shirttexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823                 }
2824                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2829                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2830                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2833                         );
2834                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2836
2837                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2838                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2839                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2840                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2841                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2845                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2847                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2849                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2850                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2851                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2852                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2853                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2854                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2855                 {
2856                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2857                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2858                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859                 }
2860                 else
2861                 {
2862                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863                 }
2864 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2866                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2868                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2869                 {
2870                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2871                         if (rsurface.rtlight)
2872                         {
2873                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2874                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2875                         }
2876                 }
2877                 break;
2878         }
2879 }
2880
2881 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2882 {
2883         // select a permutation of the lighting shader appropriate to this
2884         // combination of texture, entity, light source, and fogging, only use the
2885         // minimum features necessary to avoid wasting rendering time in the
2886         // fragment shader on features that are not being used
2887         unsigned int permutation = 0;
2888         unsigned int mode = 0;
2889         const float *lightcolorbase = rtlight->currentcolor;
2890         float ambientscale = rtlight->ambientscale;
2891         float diffusescale = rtlight->diffusescale;
2892         float specularscale = rtlight->specularscale;
2893         // this is the location of the light in view space
2894         vec3_t viewlightorigin;
2895         // this transforms from view space (camera) to light space (cubemap)
2896         matrix4x4_t viewtolight;
2897         matrix4x4_t lighttoview;
2898         float viewtolight16f[16];
2899         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2900         // light source
2901         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2902         if (rtlight->currentcubemap != r_texture_whitecube)
2903                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2904         if (diffusescale > 0)
2905                 permutation |= SHADERPERMUTATION_DIFFUSE;
2906         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2907                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908         if (r_shadow_usingshadowmap2d)
2909         {
2910                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2911                 if (r_shadow_shadowmapvsdct)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2913
2914                 if (r_shadow_shadowmapsampler)
2915                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2916                 if (r_shadow_shadowmappcf > 1)
2917                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2918                 else if (r_shadow_shadowmappcf)
2919                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2920         }
2921         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2922         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2923         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2924         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2925         switch(vid.renderpath)
2926         {
2927         case RENDERPATH_D3D9:
2928 #ifdef SUPPORTD3D
2929                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2930                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2931                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2932                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2935                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2937                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2938                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2940
2941                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2942                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2943                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2944                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2945                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2946                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2947 #endif
2948                 break;
2949         case RENDERPATH_D3D10:
2950                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951                 break;
2952         case RENDERPATH_D3D11:
2953                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2954                 break;
2955         case RENDERPATH_GL20:
2956         case RENDERPATH_GLES2:
2957                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2958                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2959                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2960                 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);
2961                 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);
2962                 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);
2963                 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]);
2964                 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]);
2965                 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));
2966                 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]);
2967                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2968
2969                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2970                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2971                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2973                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2974                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2975                 break;
2976         case RENDERPATH_GL11:
2977         case RENDERPATH_GL13:
2978         case RENDERPATH_GLES1:
2979                 break;
2980         case RENDERPATH_SOFT:
2981                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988                 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]);
2989                 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));
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992
2993                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2994                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2995                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2996                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2997                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2998                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2999                 break;
3000         }
3001 }
3002
3003 #define SKINFRAME_HASH 1024
3004
3005 typedef struct
3006 {
3007         int loadsequence; // incremented each level change
3008         memexpandablearray_t array;
3009         skinframe_t *hash[SKINFRAME_HASH];
3010 }
3011 r_skinframe_t;
3012 r_skinframe_t r_skinframe;
3013
3014 void R_SkinFrame_PrepareForPurge(void)
3015 {
3016         r_skinframe.loadsequence++;
3017         // wrap it without hitting zero
3018         if (r_skinframe.loadsequence >= 200)
3019                 r_skinframe.loadsequence = 1;
3020 }
3021
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 {
3024         if (!skinframe)
3025                 return;
3026         // mark the skinframe as used for the purging code
3027         skinframe->loadsequence = r_skinframe.loadsequence;
3028 }
3029
3030 void R_SkinFrame_Purge(void)
3031 {
3032         int i;
3033         skinframe_t *s;
3034         for (i = 0;i < SKINFRAME_HASH;i++)
3035         {
3036                 for (s = r_skinframe.hash[i];s;s = s->next)
3037                 {
3038                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039                         {
3040                                 if (s->merged == s->base)
3041                                         s->merged = NULL;
3042                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3044                                 R_PurgeTexture(s->merged);s->merged = NULL;
3045                                 R_PurgeTexture(s->base  );s->base   = NULL;
3046                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3047                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3048                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3049                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3050                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3051                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3052                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053                                 s->loadsequence = 0;
3054                         }
3055                 }
3056         }
3057 }
3058
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060         skinframe_t *item;
3061         char basename[MAX_QPATH];
3062
3063         Image_StripImageExtension(name, basename, sizeof(basename));
3064
3065         if( last == NULL ) {
3066                 int hashindex;
3067                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068                 item = r_skinframe.hash[hashindex];
3069         } else {
3070                 item = last->next;
3071         }
3072
3073         // linearly search through the hash bucket
3074         for( ; item ; item = item->next ) {
3075                 if( !strcmp( item->basename, basename ) ) {
3076                         return item;
3077                 }
3078         }
3079         return NULL;
3080 }
3081
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 {
3084         skinframe_t *item;
3085         int hashindex;
3086         char basename[MAX_QPATH];
3087
3088         Image_StripImageExtension(name, basename, sizeof(basename));
3089
3090         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093                         break;
3094
3095         if (!item) {
3096                 rtexture_t *dyntexture;
3097                 // check whether its a dynamic texture
3098                 dyntexture = CL_GetDynTexture( basename );
3099                 if (!add && !dyntexture)
3100                         return NULL;
3101                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102                 memset(item, 0, sizeof(*item));
3103                 strlcpy(item->basename, basename, sizeof(item->basename));
3104                 item->base = dyntexture; // either NULL or dyntexture handle
3105                 item->textureflags = textureflags;
3106                 item->comparewidth = comparewidth;
3107                 item->compareheight = compareheight;
3108                 item->comparecrc = comparecrc;
3109                 item->next = r_skinframe.hash[hashindex];
3110                 r_skinframe.hash[hashindex] = item;
3111         }
3112         else if( item->base == NULL )
3113         {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 // 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]
3117                 dyntexture = CL_GetDynTexture( basename );
3118                 item->base = dyntexture; // either NULL or dyntexture handle
3119         }
3120
3121         R_SkinFrame_MarkUsed(item);
3122         return item;
3123 }
3124
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126         { \
3127                 unsigned long long avgcolor[5], wsum; \
3128                 int pix, comp, w; \
3129                 avgcolor[0] = 0; \
3130                 avgcolor[1] = 0; \
3131                 avgcolor[2] = 0; \
3132                 avgcolor[3] = 0; \
3133                 avgcolor[4] = 0; \
3134                 wsum = 0; \
3135                 for(pix = 0; pix < cnt; ++pix) \
3136                 { \
3137                         w = 0; \
3138                         for(comp = 0; comp < 3; ++comp) \
3139                                 w += getpixel; \
3140                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3141                         { \
3142                                 ++wsum; \
3143                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                                 w = getpixel; \
3145                                 for(comp = 0; comp < 3; ++comp) \
3146                                         avgcolor[comp] += getpixel * w; \
3147                                 avgcolor[3] += w; \
3148                         } \
3149                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150                         avgcolor[4] += getpixel; \
3151                 } \
3152                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153                         avgcolor[3] = 1; \
3154                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3158         }
3159
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3162 {
3163         int j;
3164         unsigned char *pixels;
3165         unsigned char *bumppixels;
3166         unsigned char *basepixels = NULL;
3167         int basepixels_width = 0;
3168         int basepixels_height = 0;
3169         skinframe_t *skinframe;
3170         rtexture_t *ddsbase = NULL;
3171         qboolean ddshasalpha = false;
3172         float ddsavgcolor[4];
3173         char basename[MAX_QPATH];
3174         int miplevel = R_PicmipForFlags(textureflags);
3175         int savemiplevel = miplevel;
3176         int mymiplevel;
3177
3178         if (cls.state == ca_dedicated)
3179                 return NULL;
3180
3181         // return an existing skinframe if already loaded
3182         // if loading of the first image fails, don't make a new skinframe as it
3183         // would cause all future lookups of this to be missing
3184         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185         if (skinframe && skinframe->base)
3186                 return skinframe;
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         // check for DDS texture file first
3191         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192         {
3193                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3194                 if (basepixels == NULL)
3195                         return NULL;
3196         }
3197
3198         // FIXME handle miplevel
3199
3200         if (developer_loading.integer)
3201                 Con_Printf("loading skin \"%s\"\n", name);
3202
3203         // we've got some pixels to store, so really allocate this new texture now
3204         if (!skinframe)
3205                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206         skinframe->stain = NULL;
3207         skinframe->merged = NULL;
3208         skinframe->base = NULL;
3209         skinframe->pants = NULL;
3210         skinframe->shirt = NULL;
3211         skinframe->nmap = NULL;
3212         skinframe->gloss = NULL;
3213         skinframe->glow = NULL;
3214         skinframe->fog = NULL;
3215         skinframe->reflect = NULL;
3216         skinframe->hasalpha = false;
3217
3218         if (ddsbase)
3219         {
3220                 skinframe->base = ddsbase;
3221                 skinframe->hasalpha = ddshasalpha;
3222                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223                 if (r_loadfog && skinframe->hasalpha)
3224                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225                 //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]);
3226         }
3227         else
3228         {
3229                 basepixels_width = image_width;
3230                 basepixels_height = image_height;
3231                 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);
3232                 if (textureflags & TEXF_ALPHA)
3233                 {
3234                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235                         {
3236                                 if (basepixels[j] < 255)
3237                                 {
3238                                         skinframe->hasalpha = true;
3239                                         break;
3240                                 }
3241                         }
3242                         if (r_loadfog && skinframe->hasalpha)
3243                         {
3244                                 // has transparent pixels
3245                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3247                                 {
3248                                         pixels[j+0] = 255;
3249                                         pixels[j+1] = 255;
3250                                         pixels[j+2] = 255;
3251                                         pixels[j+3] = basepixels[j+3];
3252                                 }
3253                                 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);
3254                                 Mem_Free(pixels);
3255                         }
3256                 }
3257                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258                 //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]);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3263         }
3264
3265         if (r_loaddds)
3266         {
3267                 mymiplevel = savemiplevel;
3268                 if (r_loadnormalmap)
3269                         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);
3270                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 if (r_loadgloss)
3272                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276         }
3277
3278         // _norm is the name used by tenebrae and has been adopted as standard
3279         if (r_loadnormalmap && skinframe->nmap == NULL)
3280         {
3281                 mymiplevel = savemiplevel;
3282                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         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);
3285                         Mem_Free(pixels);
3286                         pixels = NULL;
3287                 }
3288                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289                 {
3290                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292                         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);
3293                         Mem_Free(pixels);
3294                         Mem_Free(bumppixels);
3295                 }
3296                 else if (r_shadow_bumpscale_basetexture.value > 0)
3297                 {
3298                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300                         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);
3301                         Mem_Free(pixels);
3302                 }
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3305         }
3306
3307         // _luma is supported only for tenebrae compatibility
3308         // _glow is the preferred name
3309         mymiplevel = savemiplevel;
3310         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))))
3311         {
3312                 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);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3315                 Mem_Free(pixels);pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3320         {
3321                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3330         {
3331                 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);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         mymiplevel = savemiplevel;
3339         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3340         {
3341                 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);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3344                 Mem_Free(pixels);
3345                 pixels = NULL;
3346         }
3347
3348         mymiplevel = savemiplevel;
3349         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3350         {
3351                 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);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3354                 Mem_Free(pixels);
3355                 pixels = NULL;
3356         }
3357
3358         if (basepixels)
3359                 Mem_Free(basepixels);
3360
3361         return skinframe;
3362 }
3363
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3366 {
3367         int i;
3368         unsigned char *temp1, *temp2;
3369         skinframe_t *skinframe;
3370
3371         if (cls.state == ca_dedicated)
3372                 return NULL;
3373
3374         // if already loaded just return it, otherwise make a new skinframe
3375         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376         if (skinframe && skinframe->base)
3377                 return skinframe;
3378
3379         skinframe->stain = NULL;
3380         skinframe->merged = NULL;
3381         skinframe->base = NULL;
3382         skinframe->pants = NULL;
3383         skinframe->shirt = NULL;
3384         skinframe->nmap = NULL;
3385         skinframe->gloss = NULL;
3386         skinframe->glow = NULL;
3387         skinframe->fog = NULL;
3388         skinframe->reflect = NULL;
3389         skinframe->hasalpha = false;
3390
3391         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392         if (!skindata)
3393                 return NULL;
3394
3395         if (developer_loading.integer)
3396                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397
3398         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399         {
3400                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401                 temp2 = temp1 + width * height * 4;
3402                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403                 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);
3404                 Mem_Free(temp1);
3405         }
3406         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3407         if (textureflags & TEXF_ALPHA)
3408         {
3409                 for (i = 3;i < width * height * 4;i += 4)
3410                 {
3411                         if (skindata[i] < 255)
3412                         {
3413                                 skinframe->hasalpha = true;
3414                                 break;
3415                         }
3416                 }
3417                 if (r_loadfog && skinframe->hasalpha)
3418                 {
3419                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420                         memcpy(fogpixels, skindata, width * height * 4);
3421                         for (i = 0;i < width * height * 4;i += 4)
3422                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424                         Mem_Free(fogpixels);
3425                 }
3426         }
3427
3428         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429         //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]);
3430
3431         return skinframe;
3432 }
3433
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 {
3436         int i;
3437         int featuresmask;
3438         skinframe_t *skinframe;
3439
3440         if (cls.state == ca_dedicated)
3441                 return NULL;
3442
3443         // if already loaded just return it, otherwise make a new skinframe
3444         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445         if (skinframe && skinframe->base)
3446                 return skinframe;
3447
3448         skinframe->stain = NULL;
3449         skinframe->merged = NULL;
3450         skinframe->base = NULL;
3451         skinframe->pants = NULL;
3452         skinframe->shirt = NULL;
3453         skinframe->nmap = NULL;
3454         skinframe->gloss = NULL;
3455         skinframe->glow = NULL;
3456         skinframe->fog = NULL;
3457         skinframe->reflect = NULL;
3458         skinframe->hasalpha = false;
3459
3460         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461         if (!skindata)
3462                 return NULL;
3463
3464         if (developer_loading.integer)
3465                 Con_Printf("loading quake skin \"%s\"\n", name);
3466
3467         // 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)
3468         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469         memcpy(skinframe->qpixels, skindata, width*height);
3470         skinframe->qwidth = width;
3471         skinframe->qheight = height;
3472
3473         featuresmask = 0;
3474         for (i = 0;i < width * height;i++)
3475                 featuresmask |= palette_featureflags[skindata[i]];
3476
3477         skinframe->hasalpha = false;
3478         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480         skinframe->qgeneratemerged = true;
3481         skinframe->qgeneratebase = skinframe->qhascolormapping;
3482         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483
3484         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485         //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]);
3486
3487         return skinframe;
3488 }
3489
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 {
3492         int width;
3493         int height;
3494         unsigned char *skindata;
3495
3496         if (!skinframe->qpixels)
3497                 return;
3498
3499         if (!skinframe->qhascolormapping)
3500                 colormapped = false;
3501
3502         if (colormapped)
3503         {
3504                 if (!skinframe->qgeneratebase)
3505                         return;
3506         }
3507         else
3508         {
3509                 if (!skinframe->qgeneratemerged)
3510                         return;
3511         }
3512
3513         width = skinframe->qwidth;
3514         height = skinframe->qheight;
3515         skindata = skinframe->qpixels;
3516
3517         if (skinframe->qgeneratenmap)
3518         {
3519                 unsigned char *temp1, *temp2;
3520                 skinframe->qgeneratenmap = false;
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 // use either a custom palette or the quake palette
3524                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 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);
3527                 Mem_Free(temp1);
3528         }
3529
3530         if (skinframe->qgenerateglow)
3531         {
3532                 skinframe->qgenerateglow = false;
3533                 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
3534         }
3535
3536         if (colormapped)
3537         {
3538                 skinframe->qgeneratebase = false;
3539                 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);
3540                 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);
3541                 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);
3542         }
3543         else
3544         {
3545                 skinframe->qgeneratemerged = false;
3546                 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);
3547         }
3548
3549         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550         {
3551                 Mem_Free(skinframe->qpixels);
3552                 skinframe->qpixels = NULL;
3553         }
3554 }
3555
3556 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)
3557 {
3558         int i;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe && skinframe->base)
3567                 return skinframe;
3568
3569         skinframe->stain = NULL;
3570         skinframe->merged = NULL;
3571         skinframe->base = NULL;
3572         skinframe->pants = NULL;
3573         skinframe->shirt = NULL;
3574         skinframe->nmap = NULL;
3575         skinframe->gloss = NULL;
3576         skinframe->glow = NULL;
3577         skinframe->fog = NULL;
3578         skinframe->reflect = NULL;
3579         skinframe->hasalpha = false;
3580
3581         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582         if (!skindata)
3583                 return NULL;
3584
3585         if (developer_loading.integer)
3586                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587
3588         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589         if (textureflags & TEXF_ALPHA)
3590         {
3591                 for (i = 0;i < width * height;i++)
3592                 {
3593                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594                         {
3595                                 skinframe->hasalpha = true;
3596                                 break;
3597                         }
3598                 }
3599                 if (r_loadfog && skinframe->hasalpha)
3600                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3601         }
3602
3603         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604         //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]);
3605
3606         return skinframe;
3607 }
3608
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 {
3611         skinframe_t *skinframe;
3612
3613         if (cls.state == ca_dedicated)
3614                 return NULL;
3615
3616         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617         skinframe->stain = NULL;
3618         skinframe->merged = NULL;
3619         skinframe->base = NULL;
3620         skinframe->pants = NULL;
3621         skinframe->shirt = NULL;
3622         skinframe->nmap = NULL;
3623         skinframe->gloss = NULL;
3624         skinframe->glow = NULL;
3625         skinframe->fog = NULL;
3626         skinframe->reflect = NULL;
3627         skinframe->hasalpha = false;
3628
3629         skinframe->avgcolor[0] = rand() / RAND_MAX;
3630         skinframe->avgcolor[1] = rand() / RAND_MAX;
3631         skinframe->avgcolor[2] = rand() / RAND_MAX;
3632         skinframe->avgcolor[3] = 1;
3633
3634         return skinframe;
3635 }
3636
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3639 {
3640         const char *suffix;
3641         qboolean flipx, flipy, flipdiagonal;
3642 }
3643 suffixinfo_t;
3644 static suffixinfo_t suffix[3][6] =
3645 {
3646         {
3647                 {"px",   false, false, false},
3648                 {"nx",   false, false, false},
3649                 {"py",   false, false, false},
3650                 {"ny",   false, false, false},
3651                 {"pz",   false, false, false},
3652                 {"nz",   false, false, false}
3653         },
3654         {
3655                 {"posx", false, false, false},
3656                 {"negx", false, false, false},
3657                 {"posy", false, false, false},
3658                 {"negy", false, false, false},
3659                 {"posz", false, false, false},
3660                 {"negz", false, false, false}
3661         },
3662         {
3663                 {"rt",    true, false,  true},
3664                 {"lf",   false,  true,  true},
3665                 {"ft",    true,  true, false},
3666                 {"bk",   false, false, false},
3667                 {"up",    true, false,  true},
3668                 {"dn",    true, false,  true}
3669         }
3670 };
3671
3672 static int componentorder[4] = {0, 1, 2, 3};
3673
3674 rtexture_t *R_LoadCubemap(const char *basename)
3675 {
3676         int i, j, cubemapsize;
3677         unsigned char *cubemappixels, *image_buffer;
3678         rtexture_t *cubemaptexture;
3679         char name[256];
3680         // must start 0 so the first loadimagepixels has no requested width/height
3681         cubemapsize = 0;
3682         cubemappixels = NULL;
3683         cubemaptexture = NULL;
3684         // keep trying different suffix groups (posx, px, rt) until one loads
3685         for (j = 0;j < 3 && !cubemappixels;j++)
3686         {
3687                 // load the 6 images in the suffix group
3688                 for (i = 0;i < 6;i++)
3689                 {
3690                         // generate an image name based on the base and and suffix
3691                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692                         // load it
3693                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3694                         {
3695                                 // an image loaded, make sure width and height are equal
3696                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697                                 {
3698                                         // if this is the first image to load successfully, allocate the cubemap memory
3699                                         if (!cubemappixels && image_width >= 1)
3700                                         {
3701                                                 cubemapsize = image_width;
3702                                                 // note this clears to black, so unavailable sides are black
3703                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704                                         }
3705                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706                                         if (cubemappixels)
3707                                                 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);
3708                                 }
3709                                 else
3710                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711                                 // free the image
3712                                 Mem_Free(image_buffer);
3713                         }
3714                 }
3715         }
3716         // if a cubemap loaded, upload it
3717         if (cubemappixels)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_Printf("loading cubemap \"%s\"\n", basename);
3721
3722                 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);
3723                 Mem_Free(cubemappixels);
3724         }
3725         else
3726         {
3727                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728                 if (developer_loading.integer)
3729                 {
3730                         Con_Printf("(tried tried images ");
3731                         for (j = 0;j < 3;j++)
3732                                 for (i = 0;i < 6;i++)
3733                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734                         Con_Print(" and was unable to find any of them).\n");
3735                 }
3736         }
3737         return cubemaptexture;
3738 }
3739
3740 rtexture_t *R_GetCubemap(const char *basename)
3741 {
3742         int i;
3743         for (i = 0;i < r_texture_numcubemaps;i++)
3744                 if (r_texture_cubemaps[i] != NULL)
3745                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3746                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3747         if (i >= MAX_CUBEMAPS)
3748                 return r_texture_whitecube;
3749         r_texture_numcubemaps++;
3750         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3751         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3752         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3753         return r_texture_cubemaps[i]->texture;
3754 }
3755
3756 void R_FreeCubemap(const char *basename)
3757 {
3758         int i;
3759
3760         for (i = 0;i < r_texture_numcubemaps;i++)
3761         {
3762                 if (r_texture_cubemaps[i] != NULL)
3763                 {
3764                         if (r_texture_cubemaps[i]->texture)
3765                         {
3766                                 if (developer_loading.integer)
3767                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3768                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3769                                 Mem_Free(r_texture_cubemaps[i]);
3770                                 r_texture_cubemaps[i] = NULL;
3771                         }
3772                 }
3773         }
3774 }
3775
3776 void R_FreeCubemaps(void)
3777 {
3778         int i;
3779         for (i = 0;i < r_texture_numcubemaps;i++)
3780         {
3781                 if (developer_loading.integer)
3782                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3783                 if (r_texture_cubemaps[i] != NULL)
3784                 {
3785                         if (r_texture_cubemaps[i]->texture)
3786                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3787                         Mem_Free(r_texture_cubemaps[i]);
3788                 }
3789         }
3790         r_texture_numcubemaps = 0;
3791 }
3792
3793 void R_Main_FreeViewCache(void)
3794 {
3795         if (r_refdef.viewcache.entityvisible)
3796                 Mem_Free(r_refdef.viewcache.entityvisible);
3797         if (r_refdef.viewcache.world_pvsbits)
3798                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3799         if (r_refdef.viewcache.world_leafvisible)
3800                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3801         if (r_refdef.viewcache.world_surfacevisible)
3802                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3803         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3804 }
3805
3806 void R_Main_ResizeViewCache(void)
3807 {
3808         int numentities = r_refdef.scene.numentities;
3809         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3810         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3811         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3812         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3813         if (r_refdef.viewcache.maxentities < numentities)
3814         {
3815                 r_refdef.viewcache.maxentities = numentities;
3816                 if (r_refdef.viewcache.entityvisible)
3817                         Mem_Free(r_refdef.viewcache.entityvisible);
3818                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3819         }
3820         if (r_refdef.viewcache.world_numclusters != numclusters)
3821         {
3822                 r_refdef.viewcache.world_numclusters = numclusters;
3823                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3824                 if (r_refdef.viewcache.world_pvsbits)
3825                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3826                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3827         }
3828         if (r_refdef.viewcache.world_numleafs != numleafs)
3829         {
3830                 r_refdef.viewcache.world_numleafs = numleafs;
3831                 if (r_refdef.viewcache.world_leafvisible)
3832                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3833                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3834         }
3835         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3836         {
3837                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3838                 if (r_refdef.viewcache.world_surfacevisible)
3839                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3840                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3841         }
3842 }
3843
3844 extern rtexture_t *loadingscreentexture;
3845 void gl_main_start(void)
3846 {
3847         loadingscreentexture = NULL;
3848         r_texture_blanknormalmap = NULL;
3849         r_texture_white = NULL;
3850         r_texture_grey128 = NULL;
3851         r_texture_black = NULL;
3852         r_texture_whitecube = NULL;
3853         r_texture_normalizationcube = NULL;
3854         r_texture_fogattenuation = NULL;
3855         r_texture_fogheighttexture = NULL;
3856         r_texture_gammaramps = NULL;
3857         r_texture_numcubemaps = 0;
3858
3859         r_loaddds = r_texture_dds_load.integer != 0;
3860         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3861
3862         switch(vid.renderpath)
3863         {
3864         case RENDERPATH_GL20:
3865         case RENDERPATH_D3D9:
3866         case RENDERPATH_D3D10:
3867         case RENDERPATH_D3D11:
3868         case RENDERPATH_SOFT:
3869         case RENDERPATH_GLES2:
3870                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3871                 Cvar_SetValueQuick(&gl_combine, 1);
3872                 Cvar_SetValueQuick(&r_glsl, 1);
3873                 r_loadnormalmap = true;
3874                 r_loadgloss = true;
3875                 r_loadfog = false;
3876                 break;
3877         case RENDERPATH_GL13:
3878         case RENDERPATH_GLES1:
3879                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3880                 Cvar_SetValueQuick(&gl_combine, 1);
3881                 Cvar_SetValueQuick(&r_glsl, 0);
3882                 r_loadnormalmap = false;
3883                 r_loadgloss = false;
3884                 r_loadfog = true;
3885                 break;
3886         case RENDERPATH_GL11:
3887                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3888                 Cvar_SetValueQuick(&gl_combine, 0);
3889                 Cvar_SetValueQuick(&r_glsl, 0);
3890                 r_loadnormalmap = false;
3891                 r_loadgloss = false;
3892                 r_loadfog = true;
3893                 break;
3894         }
3895
3896         R_AnimCache_Free();
3897         R_FrameData_Reset();
3898
3899         r_numqueries = 0;
3900         r_maxqueries = 0;
3901         memset(r_queries, 0, sizeof(r_queries));
3902
3903         r_qwskincache = NULL;
3904         r_qwskincache_size = 0;
3905
3906         // due to caching of texture_t references, the collision cache must be reset
3907         Collision_Cache_Reset(true);
3908
3909         // set up r_skinframe loading system for textures
3910         memset(&r_skinframe, 0, sizeof(r_skinframe));
3911         r_skinframe.loadsequence = 1;
3912         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3913
3914         r_main_texturepool = R_AllocTexturePool();
3915         R_BuildBlankTextures();
3916         R_BuildNoTexture();
3917         if (vid.support.arb_texture_cube_map)
3918         {
3919                 R_BuildWhiteCube();
3920                 R_BuildNormalizationCube();
3921         }
3922         r_texture_fogattenuation = NULL;
3923         r_texture_fogheighttexture = NULL;
3924         r_texture_gammaramps = NULL;
3925         //r_texture_fogintensity = NULL;
3926         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3927         memset(&r_waterstate, 0, sizeof(r_waterstate));
3928         r_glsl_permutation = NULL;
3929         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3930         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3931         glslshaderstring = NULL;
3932 #ifdef SUPPORTD3D
3933         r_hlsl_permutation = NULL;
3934         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3935         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3936 #endif
3937         hlslshaderstring = NULL;
3938         memset(&r_svbsp, 0, sizeof (r_svbsp));
3939
3940         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3941         r_texture_numcubemaps = 0;
3942
3943         r_refdef.fogmasktable_density = 0;
3944 }
3945
3946 void gl_main_shutdown(void)
3947 {
3948         R_AnimCache_Free();
3949         R_FrameData_Reset();
3950
3951         R_Main_FreeViewCache();
3952
3953         switch(vid.renderpath)
3954         {
3955         case RENDERPATH_GL11:
3956         case RENDERPATH_GL13:
3957         case RENDERPATH_GL20:
3958         case RENDERPATH_GLES1:
3959         case RENDERPATH_GLES2:
3960                 if (r_maxqueries)
3961                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3962                 break;
3963         case RENDERPATH_D3D9:
3964                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3965                 break;
3966         case RENDERPATH_D3D10:
3967                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3968                 break;
3969         case RENDERPATH_D3D11:
3970                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3971                 break;
3972         case RENDERPATH_SOFT:
3973                 break;
3974         }
3975
3976         r_numqueries = 0;
3977         r_maxqueries = 0;
3978         memset(r_queries, 0, sizeof(r_queries));
3979
3980         r_qwskincache = NULL;
3981         r_qwskincache_size = 0;
3982
3983         // clear out the r_skinframe state
3984         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3985         memset(&r_skinframe, 0, sizeof(r_skinframe));
3986
3987         if (r_svbsp.nodes)
3988                 Mem_Free(r_svbsp.nodes);
3989         memset(&r_svbsp, 0, sizeof (r_svbsp));
3990         R_FreeTexturePool(&r_main_texturepool);
3991         loadingscreentexture = NULL;
3992         r_texture_blanknormalmap = NULL;
3993         r_texture_white = NULL;
3994         r_texture_grey128 = NULL;
3995         r_texture_black = NULL;
3996         r_texture_whitecube = NULL;
3997         r_texture_normalizationcube = NULL;
3998         r_texture_fogattenuation = NULL;
3999         r_texture_fogheighttexture = NULL;
4000         r_texture_gammaramps = NULL;
4001         r_texture_numcubemaps = 0;
4002         //r_texture_fogintensity = NULL;
4003         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4004         memset(&r_waterstate, 0, sizeof(r_waterstate));
4005         R_GLSL_Restart_f();
4006
4007         r_glsl_permutation = NULL;
4008         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4009         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4010         glslshaderstring = NULL;
4011 #ifdef SUPPORTD3D
4012         r_hlsl_permutation = NULL;
4013         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4014         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4015 #endif
4016         hlslshaderstring = NULL;
4017 }
4018
4019 extern void CL_ParseEntityLump(char *entitystring);
4020 void gl_main_newmap(void)
4021 {
4022         // FIXME: move this code to client
4023         char *entities, entname[MAX_QPATH];
4024         if (r_qwskincache)
4025                 Mem_Free(r_qwskincache);
4026         r_qwskincache = NULL;
4027         r_qwskincache_size = 0;
4028         if (cl.worldmodel)
4029         {
4030                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4031                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4032                 {
4033                         CL_ParseEntityLump(entities);
4034                         Mem_Free(entities);
4035                         return;
4036                 }
4037                 if (cl.worldmodel->brush.entities)
4038                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4039         }
4040         R_Main_FreeViewCache();
4041
4042         R_FrameData_Reset();
4043 }
4044
4045 void GL_Main_Init(void)
4046 {
4047         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4048
4049         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4050         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4051         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4052         if (gamemode == GAME_NEHAHRA)
4053         {
4054                 Cvar_RegisterVariable (&gl_fogenable);
4055                 Cvar_RegisterVariable (&gl_fogdensity);
4056                 Cvar_RegisterVariable (&gl_fogred);
4057                 Cvar_RegisterVariable (&gl_foggreen);
4058                 Cvar_RegisterVariable (&gl_fogblue);
4059                 Cvar_RegisterVariable (&gl_fogstart);
4060                 Cvar_RegisterVariable (&gl_fogend);
4061                 Cvar_RegisterVariable (&gl_skyclip);
4062         }
4063         Cvar_RegisterVariable(&r_motionblur);
4064         Cvar_RegisterVariable(&r_motionblur_maxblur);
4065         Cvar_RegisterVariable(&r_motionblur_bmin);
4066         Cvar_RegisterVariable(&r_motionblur_vmin);
4067         Cvar_RegisterVariable(&r_motionblur_vmax);
4068         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4069         Cvar_RegisterVariable(&r_motionblur_randomize);
4070         Cvar_RegisterVariable(&r_damageblur);
4071         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4072         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4073         Cvar_RegisterVariable(&r_equalize_entities_by);
4074         Cvar_RegisterVariable(&r_equalize_entities_to);
4075         Cvar_RegisterVariable(&r_depthfirst);
4076         Cvar_RegisterVariable(&r_useinfinitefarclip);
4077         Cvar_RegisterVariable(&r_farclip_base);
4078         Cvar_RegisterVariable(&r_farclip_world);
4079         Cvar_RegisterVariable(&r_nearclip);
4080         Cvar_RegisterVariable(&r_deformvertexes);
4081         Cvar_RegisterVariable(&r_transparent);
4082         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4083         Cvar_RegisterVariable(&r_showoverdraw);
4084         Cvar_RegisterVariable(&r_showbboxes);
4085         Cvar_RegisterVariable(&r_showsurfaces);
4086         Cvar_RegisterVariable(&r_showtris);
4087         Cvar_RegisterVariable(&r_shownormals);
4088         Cvar_RegisterVariable(&r_showlighting);
4089         Cvar_RegisterVariable(&r_showshadowvolumes);
4090         Cvar_RegisterVariable(&r_showcollisionbrushes);
4091         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4092         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4093         Cvar_RegisterVariable(&r_showdisabledepthtest);
4094         Cvar_RegisterVariable(&r_drawportals);
4095         Cvar_RegisterVariable(&r_drawentities);
4096         Cvar_RegisterVariable(&r_draw2d);
4097         Cvar_RegisterVariable(&r_drawworld);
4098         Cvar_RegisterVariable(&r_cullentities_trace);
4099         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4100         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4101         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4102         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4103         Cvar_RegisterVariable(&r_drawviewmodel);
4104         Cvar_RegisterVariable(&r_drawexteriormodel);
4105         Cvar_RegisterVariable(&r_speeds);
4106         Cvar_RegisterVariable(&r_fullbrights);
4107         Cvar_RegisterVariable(&r_wateralpha);
4108         Cvar_RegisterVariable(&r_dynamic);
4109         Cvar_RegisterVariable(&r_fakelight);
4110         Cvar_RegisterVariable(&r_fakelight_intensity);
4111         Cvar_RegisterVariable(&r_fullbright);
4112         Cvar_RegisterVariable(&r_shadows);
4113         Cvar_RegisterVariable(&r_shadows_darken);
4114         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4115         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4116         Cvar_RegisterVariable(&r_shadows_throwdistance);
4117         Cvar_RegisterVariable(&r_shadows_throwdirection);
4118         Cvar_RegisterVariable(&r_shadows_focus);
4119         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4120         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4121         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4122         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4123         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4124         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4125         Cvar_RegisterVariable(&r_fog_exp2);
4126         Cvar_RegisterVariable(&r_fog_clear);
4127         Cvar_RegisterVariable(&r_drawfog);
4128         Cvar_RegisterVariable(&r_transparentdepthmasking);
4129         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4130         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4131         Cvar_RegisterVariable(&r_texture_dds_load);
4132         Cvar_RegisterVariable(&r_texture_dds_save);
4133         Cvar_RegisterVariable(&r_textureunits);
4134         Cvar_RegisterVariable(&gl_combine);
4135         Cvar_RegisterVariable(&r_viewfbo);
4136         Cvar_RegisterVariable(&r_viewscale);
4137         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4138         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4139         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4140         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4141         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4142         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4143         Cvar_RegisterVariable(&r_glsl);
4144         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4145         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4146         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4147         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4148         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4149         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4150         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4151         Cvar_RegisterVariable(&r_glsl_postprocess);
4152         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4153         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4154         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4155         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4156         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4157         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4158         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4159         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4160
4161         Cvar_RegisterVariable(&r_water);
4162         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4163         Cvar_RegisterVariable(&r_water_clippingplanebias);
4164         Cvar_RegisterVariable(&r_water_refractdistort);
4165         Cvar_RegisterVariable(&r_water_reflectdistort);
4166         Cvar_RegisterVariable(&r_water_scissormode);
4167         Cvar_RegisterVariable(&r_lerpsprites);
4168         Cvar_RegisterVariable(&r_lerpmodels);
4169         Cvar_RegisterVariable(&r_lerplightstyles);
4170         Cvar_RegisterVariable(&r_waterscroll);
4171         Cvar_RegisterVariable(&r_bloom);
4172         Cvar_RegisterVariable(&r_bloom_colorscale);
4173         Cvar_RegisterVariable(&r_bloom_brighten);
4174         Cvar_RegisterVariable(&r_bloom_blur);
4175         Cvar_RegisterVariable(&r_bloom_resolution);
4176         Cvar_RegisterVariable(&r_bloom_colorexponent);
4177         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4178         Cvar_RegisterVariable(&r_hdr);
4179         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4180         Cvar_RegisterVariable(&r_hdr_glowintensity);
4181         Cvar_RegisterVariable(&r_hdr_range);
4182         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4183         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4184         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4185         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4186         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4187         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4188         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4189         Cvar_RegisterVariable(&developer_texturelogging);
4190         Cvar_RegisterVariable(&gl_lightmaps);
4191         Cvar_RegisterVariable(&r_test);
4192         Cvar_RegisterVariable(&r_glsl_saturation);
4193         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4194         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4195         Cvar_RegisterVariable(&r_framedatasize);
4196         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4197                 Cvar_SetValue("r_fullbrights", 0);
4198         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4199
4200         Cvar_RegisterVariable(&r_track_sprites);
4201         Cvar_RegisterVariable(&r_track_sprites_flags);
4202         Cvar_RegisterVariable(&r_track_sprites_scalew);
4203         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4204         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4205         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4206         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4207         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4208 }
4209
4210 extern void R_Textures_Init(void);
4211 extern void GL_Draw_Init(void);
4212 extern void GL_Main_Init(void);
4213 extern void R_Shadow_Init(void);
4214 extern void R_Sky_Init(void);
4215 extern void GL_Surf_Init(void);
4216 extern void R_Particles_Init(void);
4217 extern void R_Explosion_Init(void);
4218 extern void gl_backend_init(void);
4219 extern void Sbar_Init(void);
4220 extern void R_LightningBeams_Init(void);
4221 extern void Mod_RenderInit(void);
4222 extern void Font_Init(void);
4223
4224 void Render_Init(void)
4225 {
4226         gl_backend_init();
4227         R_Textures_Init();
4228         GL_Main_Init();
4229         Font_Init();
4230         GL_Draw_Init();
4231         R_Shadow_Init();
4232         R_Sky_Init();
4233         GL_Surf_Init();
4234         Sbar_Init();
4235         R_Particles_Init();
4236         R_Explosion_Init();
4237         R_LightningBeams_Init();
4238         Mod_RenderInit();
4239 }
4240
4241 /*
4242 ===============
4243 GL_Init
4244 ===============
4245 */
4246 extern char *ENGINE_EXTENSIONS;
4247 void GL_Init (void)
4248 {
4249         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4250         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4251         gl_version = (const char *)qglGetString(GL_VERSION);
4252         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4253
4254         if (!gl_extensions)
4255                 gl_extensions = "";
4256         if (!gl_platformextensions)
4257                 gl_platformextensions = "";
4258
4259         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4260         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4261         Con_Printf("GL_VERSION: %s\n", gl_version);
4262         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4263         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4264
4265         VID_CheckExtensions();
4266
4267         // LordHavoc: report supported extensions
4268         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4269
4270         // clear to black (loading plaque will be seen over this)
4271         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4272 }
4273
4274 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4275 {
4276         int i;
4277         mplane_t *p;
4278         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4279         {
4280                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4281                 if (i == 4)
4282                         continue;
4283                 p = r_refdef.view.frustum + i;
4284                 switch(p->signbits)
4285                 {
4286                 default:
4287                 case 0:
4288                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4289                                 return true;
4290                         break;
4291                 case 1:
4292                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4293                                 return true;
4294                         break;
4295                 case 2:
4296                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4297                                 return true;
4298                         break;
4299                 case 3:
4300                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4301                                 return true;
4302                         break;
4303                 case 4:
4304                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 case 5:
4308                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4309                                 return true;
4310                         break;
4311                 case 6:
4312                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 case 7:
4316                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4317                                 return true;
4318                         break;
4319                 }
4320         }
4321         return false;
4322 }
4323
4324 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4325 {
4326         int i;
4327         const mplane_t *p;
4328         for (i = 0;i < numplanes;i++)
4329         {
4330                 p = planes + i;
4331                 switch(p->signbits)
4332                 {
4333                 default:
4334                 case 0:
4335                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4336                                 return true;
4337                         break;
4338                 case 1:
4339                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4340                                 return true;
4341                         break;
4342                 case 2:
4343                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4344                                 return true;
4345                         break;
4346                 case 3:
4347                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4348                                 return true;
4349                         break;
4350                 case 4:
4351                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4352                                 return true;
4353                         break;
4354                 case 5:
4355                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4356                                 return true;
4357                         break;
4358                 case 6:
4359                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4360                                 return true;
4361                         break;
4362                 case 7:
4363                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4364                                 return true;
4365                         break;
4366                 }
4367         }
4368         return false;
4369 }
4370
4371 //==================================================================================
4372
4373 // LordHavoc: this stores temporary data used within the same frame
4374
4375 typedef struct r_framedata_mem_s
4376 {
4377         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4378         size_t size; // how much usable space
4379         size_t current; // how much space in use
4380         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4381         size_t wantedsize; // how much space was allocated
4382         unsigned char *data; // start of real data (16byte aligned)
4383 }
4384 r_framedata_mem_t;
4385
4386 static r_framedata_mem_t *r_framedata_mem;
4387
4388 void R_FrameData_Reset(void)
4389 {
4390         while (r_framedata_mem)
4391         {
4392                 r_framedata_mem_t *next = r_framedata_mem->purge;
4393                 Mem_Free(r_framedata_mem);
4394                 r_framedata_mem = next;
4395         }
4396 }
4397
4398 void R_FrameData_Resize(void)
4399 {
4400         size_t wantedsize;
4401         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4402         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4403         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4404         {
4405                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4406                 newmem->wantedsize = wantedsize;
4407                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4408                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4409                 newmem->current = 0;
4410                 newmem->mark = 0;
4411                 newmem->purge = r_framedata_mem;
4412                 r_framedata_mem = newmem;
4413         }
4414 }
4415
4416 void R_FrameData_NewFrame(void)
4417 {
4418         R_FrameData_Resize();
4419         if (!r_framedata_mem)
4420                 return;
4421         // if we ran out of space on the last frame, free the old memory now
4422         while (r_framedata_mem->purge)
4423         {
4424                 // repeatedly remove the second item in the list, leaving only head
4425                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4426                 Mem_Free(r_framedata_mem->purge);
4427                 r_framedata_mem->purge = next;
4428         }
4429         // reset the current mem pointer
4430         r_framedata_mem->current = 0;
4431         r_framedata_mem->mark = 0;
4432 }
4433
4434 void *R_FrameData_Alloc(size_t size)
4435 {
4436         void *data;
4437
4438         // align to 16 byte boundary - the data pointer is already aligned, so we
4439         // only need to ensure the size of every allocation is also aligned
4440         size = (size + 15) & ~15;
4441
4442         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4443         {
4444                 // emergency - we ran out of space, allocate more memory
4445                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4446                 R_FrameData_Resize();
4447         }
4448
4449         data = r_framedata_mem->data + r_framedata_mem->current;
4450         r_framedata_mem->current += size;
4451
4452         // count the usage for stats
4453         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4454         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4455
4456         return (void *)data;
4457 }
4458
4459 void *R_FrameData_Store(size_t size, void *data)
4460 {
4461         void *d = R_FrameData_Alloc(size);
4462         if (d && data)
4463                 memcpy(d, data, size);
4464         return d;
4465 }
4466
4467 void R_FrameData_SetMark(void)
4468 {
4469         if (!r_framedata_mem)
4470                 return;
4471         r_framedata_mem->mark = r_framedata_mem->current;
4472 }
4473
4474 void R_FrameData_ReturnToMark(void)
4475 {
4476         if (!r_framedata_mem)
4477                 return;
4478         r_framedata_mem->current = r_framedata_mem->mark;
4479 }
4480
4481 //==================================================================================
4482
4483 // LordHavoc: animcache originally written by Echon, rewritten since then
4484
4485 /**
4486  * Animation cache prevents re-generating mesh data for an animated model
4487  * multiple times in one frame for lighting, shadowing, reflections, etc.
4488  */
4489
4490 void R_AnimCache_Free(void)
4491 {
4492 }
4493
4494 void R_AnimCache_ClearCache(void)
4495 {
4496         int i;
4497         entity_render_t *ent;
4498
4499         for (i = 0;i < r_refdef.scene.numentities;i++)
4500         {
4501                 ent = r_refdef.scene.entities[i];
4502                 ent->animcache_vertex3f = NULL;
4503                 ent->animcache_normal3f = NULL;
4504                 ent->animcache_svector3f = NULL;
4505                 ent->animcache_tvector3f = NULL;
4506                 ent->animcache_vertexmesh = NULL;
4507                 ent->animcache_vertex3fbuffer = NULL;
4508                 ent->animcache_vertexmeshbuffer = NULL;
4509         }
4510 }
4511
4512 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4513 {
4514         int i;
4515
4516         // check if we need the meshbuffers
4517         if (!vid.useinterleavedarrays)
4518                 return;
4519
4520         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4521                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4522         // TODO: upload vertex3f buffer?
4523         if (ent->animcache_vertexmesh)
4524         {
4525                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4526                 for (i = 0;i < numvertices;i++)
4527                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4528                 if (ent->animcache_svector3f)
4529                         for (i = 0;i < numvertices;i++)
4530                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4531                 if (ent->animcache_tvector3f)
4532                         for (i = 0;i < numvertices;i++)
4533                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4534                 if (ent->animcache_normal3f)
4535                         for (i = 0;i < numvertices;i++)
4536                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4537                 // TODO: upload vertexmeshbuffer?
4538         }
4539 }
4540
4541 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4542 {
4543         dp_model_t *model = ent->model;
4544         int numvertices;
4545         // see if it's already cached this frame
4546         if (ent->animcache_vertex3f)
4547         {
4548                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4549                 if (wantnormals || wanttangents)
4550                 {
4551                         if (ent->animcache_normal3f)
4552                                 wantnormals = false;
4553                         if (ent->animcache_svector3f)
4554                                 wanttangents = false;
4555                         if (wantnormals || wanttangents)
4556                         {
4557                                 numvertices = model->surfmesh.num_vertices;
4558                                 if (wantnormals)
4559                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4560                                 if (wanttangents)
4561                                 {
4562                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                                 }
4565                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4566                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4567                         }
4568                 }
4569         }
4570         else
4571         {
4572                 // see if this ent is worth caching
4573                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4574                         return false;
4575                 // get some memory for this entity and generate mesh data
4576                 numvertices = model->surfmesh.num_vertices;
4577                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4578                 if (wantnormals)
4579                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4580                 if (wanttangents)
4581                 {
4582                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4583                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4584                 }
4585                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4586                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4587         }
4588         return true;
4589 }
4590
4591 void R_AnimCache_CacheVisibleEntities(void)
4592 {
4593         int i;
4594         qboolean wantnormals = true;
4595         qboolean wanttangents = !r_showsurfaces.integer;
4596
4597         switch(vid.renderpath)
4598         {
4599         case RENDERPATH_GL20:
4600         case RENDERPATH_D3D9:
4601         case RENDERPATH_D3D10:
4602         case RENDERPATH_D3D11:
4603         case RENDERPATH_GLES2:
4604                 break;
4605         case RENDERPATH_GL11:
4606         case RENDERPATH_GL13:
4607         case RENDERPATH_GLES1:
4608                 wanttangents = false;
4609                 break;
4610         case RENDERPATH_SOFT:
4611                 break;
4612         }
4613
4614         if (r_shownormals.integer)
4615                 wanttangents = wantnormals = true;
4616
4617         // TODO: thread this
4618         // NOTE: R_PrepareRTLights() also caches entities
4619
4620         for (i = 0;i < r_refdef.scene.numentities;i++)
4621                 if (r_refdef.viewcache.entityvisible[i])
4622                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4623 }
4624
4625 //==================================================================================
4626
4627 static void R_View_UpdateEntityLighting (void)
4628 {
4629         int i;
4630         entity_render_t *ent;
4631         vec3_t tempdiffusenormal, avg;
4632         vec_t f, fa, fd, fdd;
4633         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4634
4635         for (i = 0;i < r_refdef.scene.numentities;i++)
4636         {
4637                 ent = r_refdef.scene.entities[i];
4638
4639                 // skip unseen models
4640                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4641                         continue;
4642
4643                 // skip bsp models
4644                 if (ent->model && ent->model->brush.num_leafs)
4645                 {
4646                         // TODO: use modellight for r_ambient settings on world?
4647                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4648                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4649                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4650                         continue;
4651                 }
4652
4653                 // fetch the lighting from the worldmodel data
4654                 VectorClear(ent->modellight_ambient);
4655                 VectorClear(ent->modellight_diffuse);
4656                 VectorClear(tempdiffusenormal);
4657                 if (ent->flags & RENDER_LIGHT)
4658                 {
4659                         vec3_t org;
4660                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4661
4662                         // complete lightning for lit sprites
4663                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4664                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4665                         {
4666                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4667                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4668                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4669                         }
4670                         else
4671                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4672
4673                         if(ent->flags & RENDER_EQUALIZE)
4674                         {
4675                                 // first fix up ambient lighting...
4676                                 if(r_equalize_entities_minambient.value > 0)
4677                                 {
4678                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4679                                         if(fd > 0)
4680                                         {
4681                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4682                                                 if(fa < r_equalize_entities_minambient.value * fd)
4683                                                 {
4684                                                         // solve:
4685                                                         //   fa'/fd' = minambient
4686                                                         //   fa'+0.25*fd' = fa+0.25*fd
4687                                                         //   ...
4688                                                         //   fa' = fd' * minambient
4689                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4690                                                         //   ...
4691                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4692                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4693                                                         //   ...
4694                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4695                                                         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
4696                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4697                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4698                                                 }
4699                                         }
4700                                 }
4701
4702                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4703                                 {
4704                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4705                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4706                                         f = fa + 0.25 * fd;
4707                                         if(f > 0)
4708                                         {
4709                                                 // adjust brightness and saturation to target
4710                                                 avg[0] = avg[1] = avg[2] = fa / f;
4711                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4712                                                 avg[0] = avg[1] = avg[2] = fd / f;
4713                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4714                                         }
4715                                 }
4716                         }
4717                 }
4718                 else // highly rare
4719                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4720
4721                 // move the light direction into modelspace coordinates for lighting code
4722                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4723                 if(VectorLength2(ent->modellight_lightdir) == 0)
4724                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4725                 VectorNormalize(ent->modellight_lightdir);
4726         }
4727 }
4728
4729 #define MAX_LINEOFSIGHTTRACES 64
4730
4731 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4732 {
4733         int i;
4734         vec3_t boxmins, boxmaxs;
4735         vec3_t start;
4736         vec3_t end;
4737         dp_model_t *model = r_refdef.scene.worldmodel;
4738
4739         if (!model || !model->brush.TraceLineOfSight)
4740                 return true;
4741
4742         // expand the box a little
4743         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4744         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4745         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4746         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4747         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4748         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4749
4750         // return true if eye is inside enlarged box
4751         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4752                 return true;
4753
4754         // try center
4755         VectorCopy(eye, start);
4756         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4757         if (model->brush.TraceLineOfSight(model, start, end))
4758                 return true;
4759
4760         // try various random positions
4761         for (i = 0;i < numsamples;i++)
4762         {
4763                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4764                 if (model->brush.TraceLineOfSight(model, start, end))
4765                         return true;
4766         }
4767
4768         return false;
4769 }
4770
4771
4772 static void R_View_UpdateEntityVisible (void)
4773 {
4774         int i;
4775         int renderimask;
4776         int samples;
4777         entity_render_t *ent;
4778
4779         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4780                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4781                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4782                 :                                                          RENDER_EXTERIORMODEL;
4783         if (!r_drawviewmodel.integer)
4784                 renderimask |= RENDER_VIEWMODEL;
4785         if (!r_drawexteriormodel.integer)
4786                 renderimask |= RENDER_EXTERIORMODEL;
4787         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4788         {
4789                 // worldmodel can check visibility
4790                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4791                 for (i = 0;i < r_refdef.scene.numentities;i++)
4792                 {
4793                         ent = r_refdef.scene.entities[i];
4794                         if (!(ent->flags & renderimask))
4795                         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)))
4796                         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))
4797                                 r_refdef.viewcache.entityvisible[i] = true;
4798                 }
4799         }
4800         else
4801         {
4802                 // no worldmodel or it can't check visibility
4803                 for (i = 0;i < r_refdef.scene.numentities;i++)
4804                 {
4805                         ent = r_refdef.scene.entities[i];
4806                         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));
4807                 }
4808         }
4809         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4810                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4811         {
4812                 for (i = 0;i < r_refdef.scene.numentities;i++)
4813                 {
4814                         if (!r_refdef.viewcache.entityvisible[i])
4815                                 continue;
4816                         ent = r_refdef.scene.entities[i];
4817                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4818                         {
4819                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4820                                 if (samples < 0)
4821                                         continue; // temp entities do pvs only
4822                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4823                                         ent->last_trace_visibility = realtime;
4824                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4825                                         r_refdef.viewcache.entityvisible[i] = 0;
4826                         }
4827                 }
4828         }
4829 }
4830
4831 /// only used if skyrendermasked, and normally returns false
4832 int R_DrawBrushModelsSky (void)
4833 {
4834         int i, sky;
4835         entity_render_t *ent;
4836
4837         sky = false;
4838         for (i = 0;i < r_refdef.scene.numentities;i++)
4839         {
4840                 if (!r_refdef.viewcache.entityvisible[i])
4841                         continue;
4842                 ent = r_refdef.scene.entities[i];
4843                 if (!ent->model || !ent->model->DrawSky)
4844                         continue;
4845                 ent->model->DrawSky(ent);
4846                 sky = true;
4847         }
4848         return sky;
4849 }
4850
4851 static void R_DrawNoModel(entity_render_t *ent);
4852 static void R_DrawModels(void)
4853 {
4854         int i;
4855         entity_render_t *ent;
4856
4857         for (i = 0;i < r_refdef.scene.numentities;i++)
4858         {
4859                 if (!r_refdef.viewcache.entityvisible[i])
4860                         continue;
4861                 ent = r_refdef.scene.entities[i];
4862                 r_refdef.stats.entities++;
4863                 /*
4864                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4865                 {
4866                         vec3_t f, l, u, o;
4867                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4868                         Con_Printf("R_DrawModels\n");
4869                         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]);
4870                         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);
4871                         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);
4872                 }
4873                 */
4874                 if (ent->model && ent->model->Draw != NULL)
4875                         ent->model->Draw(ent);
4876                 else
4877                         R_DrawNoModel(ent);
4878         }
4879 }
4880
4881 static void R_DrawModelsDepth(void)
4882 {
4883         int i;
4884         entity_render_t *ent;
4885
4886         for (i = 0;i < r_refdef.scene.numentities;i++)
4887         {
4888                 if (!r_refdef.viewcache.entityvisible[i])
4889                         continue;
4890                 ent = r_refdef.scene.entities[i];
4891                 if (ent->model && ent->model->DrawDepth != NULL)
4892                         ent->model->DrawDepth(ent);
4893         }
4894 }
4895
4896 static void R_DrawModelsDebug(void)
4897 {
4898         int i;
4899         entity_render_t *ent;
4900
4901         for (i = 0;i < r_refdef.scene.numentities;i++)
4902         {
4903                 if (!r_refdef.viewcache.entityvisible[i])
4904                         continue;
4905                 ent = r_refdef.scene.entities[i];
4906                 if (ent->model && ent->model->DrawDebug != NULL)
4907                         ent->model->DrawDebug(ent);
4908         }
4909 }
4910
4911 static void R_DrawModelsAddWaterPlanes(void)
4912 {
4913         int i;
4914         entity_render_t *ent;
4915
4916         for (i = 0;i < r_refdef.scene.numentities;i++)
4917         {
4918                 if (!r_refdef.viewcache.entityvisible[i])
4919                         continue;
4920                 ent = r_refdef.scene.entities[i];
4921                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4922                         ent->model->DrawAddWaterPlanes(ent);
4923         }
4924 }
4925
4926 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4927 {
4928         if (r_hdr_irisadaptation.integer)
4929         {
4930                 vec3_t ambient;
4931                 vec3_t diffuse;
4932                 vec3_t diffusenormal;
4933                 vec_t brightness;
4934                 vec_t goal;
4935                 vec_t adjust;
4936                 vec_t current;
4937                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4938                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4939                 brightness = max(0.0000001f, brightness);
4940                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4941                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4942                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4943                 current = r_hdr_irisadaptation_value.value;
4944                 if (current < goal)
4945                         current = min(current + adjust, goal);
4946                 else if (current > goal)
4947                         current = max(current - adjust, goal);
4948                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4949                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4950         }
4951         else if (r_hdr_irisadaptation_value.value != 1.0f)
4952                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4953 }
4954
4955 static void R_View_SetFrustum(const int *scissor)
4956 {
4957         int i;
4958         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4959         vec3_t forward, left, up, origin, v;
4960
4961         if(scissor)
4962         {
4963                 // flipped x coordinates (because x points left here)
4964                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4965                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4966
4967                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4968                 switch(vid.renderpath)
4969                 {
4970                         case RENDERPATH_D3D9:
4971                         case RENDERPATH_D3D10:
4972                         case RENDERPATH_D3D11:
4973                                 // non-flipped y coordinates
4974                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4975                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4976                                 break;
4977                         case RENDERPATH_SOFT:
4978                         case RENDERPATH_GL11:
4979                         case RENDERPATH_GL13:
4980                         case RENDERPATH_GL20:
4981                         case RENDERPATH_GLES1:
4982                         case RENDERPATH_GLES2:
4983                                 // non-flipped y coordinates
4984                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4985                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4986                                 break;
4987                 }
4988         }
4989
4990         // we can't trust r_refdef.view.forward and friends in reflected scenes
4991         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4992
4993 #if 0
4994         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4995         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4996         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4997         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4998         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4999         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5000         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5001         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5002         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5003         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5004         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5005         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5006 #endif
5007
5008 #if 0
5009         zNear = r_refdef.nearclip;
5010         nudge = 1.0 - 1.0 / (1<<23);
5011         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5012         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5013         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5014         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5015         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5016         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5017         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5018         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5019 #endif
5020
5021
5022
5023 #if 0
5024         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5025         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5026         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5027         r_refdef.view.frustum[0].dist = m[15] - m[12];
5028
5029         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5030         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5031         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5032         r_refdef.view.frustum[1].dist = m[15] + m[12];
5033
5034         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5035         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5036         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5037         r_refdef.view.frustum[2].dist = m[15] - m[13];
5038
5039         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5040         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5041         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5042         r_refdef.view.frustum[3].dist = m[15] + m[13];
5043
5044         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5045         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5046         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5047         r_refdef.view.frustum[4].dist = m[15] - m[14];
5048
5049         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5050         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5051         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5052         r_refdef.view.frustum[5].dist = m[15] + m[14];
5053 #endif
5054
5055         if (r_refdef.view.useperspective)
5056         {
5057                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5058                 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]);
5059                 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]);
5060                 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]);
5061                 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]);
5062
5063                 // then the normals from the corners relative to origin
5064                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5065                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5066                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5067                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5068
5069                 // in a NORMAL view, forward cross left == up
5070                 // in a REFLECTED view, forward cross left == down
5071                 // so our cross products above need to be adjusted for a left handed coordinate system
5072                 CrossProduct(forward, left, v);
5073                 if(DotProduct(v, up) < 0)
5074                 {
5075                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5076                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5077                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5078                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5079                 }
5080
5081                 // Leaving those out was a mistake, those were in the old code, and they
5082                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5083                 // I couldn't reproduce it after adding those normalizations. --blub
5084                 VectorNormalize(r_refdef.view.frustum[0].normal);
5085                 VectorNormalize(r_refdef.view.frustum[1].normal);
5086                 VectorNormalize(r_refdef.view.frustum[2].normal);
5087                 VectorNormalize(r_refdef.view.frustum[3].normal);
5088
5089                 // make the corners absolute
5090                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5091                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5092                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5093                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5094
5095                 // one more normal
5096                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5097
5098                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5099                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5100                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5101                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5102                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5103         }
5104         else
5105         {
5106                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5107                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5108                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5109                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5110                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5111                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5112                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5113                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5114                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5115                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5116         }
5117         r_refdef.view.numfrustumplanes = 5;
5118
5119         if (r_refdef.view.useclipplane)
5120         {
5121                 r_refdef.view.numfrustumplanes = 6;
5122                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5123         }
5124
5125         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5126                 PlaneClassify(r_refdef.view.frustum + i);
5127
5128         // LordHavoc: note to all quake engine coders, Quake had a special case
5129         // for 90 degrees which assumed a square view (wrong), so I removed it,
5130         // Quake2 has it disabled as well.
5131
5132         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5133         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5134         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5135         //PlaneClassify(&frustum[0]);
5136
5137         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5138         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5139         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5140         //PlaneClassify(&frustum[1]);
5141
5142         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5143         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5144         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5145         //PlaneClassify(&frustum[2]);
5146
5147         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5148         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5149         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5150         //PlaneClassify(&frustum[3]);
5151
5152         // nearclip plane
5153         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5154         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5155         //PlaneClassify(&frustum[4]);
5156 }
5157
5158 void R_View_UpdateWithScissor(const int *myscissor)
5159 {
5160         R_Main_ResizeViewCache();
5161         R_View_SetFrustum(myscissor);
5162         R_View_WorldVisibility(r_refdef.view.useclipplane);
5163         R_View_UpdateEntityVisible();
5164         R_View_UpdateEntityLighting();
5165 }
5166
5167 void R_View_Update(void)
5168 {
5169         R_Main_ResizeViewCache();
5170         R_View_SetFrustum(NULL);
5171         R_View_WorldVisibility(r_refdef.view.useclipplane);
5172         R_View_UpdateEntityVisible();
5173         R_View_UpdateEntityLighting();
5174 }
5175
5176 float viewscalefpsadjusted = 1.0f;
5177
5178 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5179 {
5180         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5181         scale = bound(0.03125f, scale, 1.0f);
5182         *outwidth = (int)ceil(width * scale);
5183         *outheight = (int)ceil(height * scale);
5184 }
5185
5186 void R_Mesh_SetMainRenderTargets(void)
5187 {
5188         if (r_bloomstate.fbo_framebuffer)
5189                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5190         else
5191                 R_Mesh_ResetRenderTargets();
5192 }
5193
5194 void R_SetupView(qboolean allowwaterclippingplane)
5195 {
5196         const float *customclipplane = NULL;
5197         float plane[4];
5198         int scaledwidth, scaledheight;
5199         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5200         {
5201                 // LordHavoc: couldn't figure out how to make this approach the
5202                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5203                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5204                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5205                         dist = r_refdef.view.clipplane.dist;
5206                 plane[0] = r_refdef.view.clipplane.normal[0];
5207                 plane[1] = r_refdef.view.clipplane.normal[1];
5208                 plane[2] = r_refdef.view.clipplane.normal[2];
5209                 plane[3] = -dist;
5210                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5211         }
5212
5213         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5214         if (!r_refdef.view.useperspective)
5215                 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);
5216         else if (vid.stencil && r_useinfinitefarclip.integer)
5217                 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);
5218         else
5219                 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);
5220         R_Mesh_SetMainRenderTargets();
5221         R_SetViewport(&r_refdef.view.viewport);
5222         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5223         {
5224                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5225                 float screenplane[4];
5226                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5227                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5228                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5229                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5230                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5231         }
5232 }
5233
5234 void R_EntityMatrix(const matrix4x4_t *matrix)
5235 {
5236         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5237         {
5238                 gl_modelmatrixchanged = false;
5239                 gl_modelmatrix = *matrix;
5240                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5241                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5242                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5243                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5244                 CHECKGLERROR
5245                 switch(vid.renderpath)
5246                 {
5247                 case RENDERPATH_D3D9:
5248 #ifdef SUPPORTD3D
5249                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5250                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5251 #endif
5252                         break;
5253                 case RENDERPATH_D3D10:
5254                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5255                         break;
5256                 case RENDERPATH_D3D11:
5257                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5258                         break;
5259                 case RENDERPATH_GL11:
5260                 case RENDERPATH_GL13:
5261                 case RENDERPATH_GLES1:
5262                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5263                         break;
5264                 case RENDERPATH_SOFT:
5265                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5266                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5267                         break;
5268                 case RENDERPATH_GL20:
5269                 case RENDERPATH_GLES2:
5270                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5271                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5272                         break;
5273                 }
5274         }
5275 }
5276
5277 void R_ResetViewRendering2D(void)
5278 {
5279         r_viewport_t viewport;
5280         DrawQ_Finish();
5281
5282         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5283         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);
5284         R_Mesh_ResetRenderTargets();
5285         R_SetViewport(&viewport);
5286         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5287         GL_Color(1, 1, 1, 1);
5288         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5289         GL_BlendFunc(GL_ONE, GL_ZERO);
5290         GL_ScissorTest(false);
5291         GL_DepthMask(false);
5292         GL_DepthRange(0, 1);
5293         GL_DepthTest(false);
5294         GL_DepthFunc(GL_LEQUAL);
5295         R_EntityMatrix(&identitymatrix);
5296         R_Mesh_ResetTextureState();
5297         GL_PolygonOffset(0, 0);
5298         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5299         switch(vid.renderpath)
5300         {
5301         case RENDERPATH_GL11:
5302         case RENDERPATH_GL13:
5303         case RENDERPATH_GL20:
5304         case RENDERPATH_GLES1:
5305         case RENDERPATH_GLES2:
5306                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5307                 break;
5308         case RENDERPATH_D3D9:
5309         case RENDERPATH_D3D10:
5310         case RENDERPATH_D3D11:
5311         case RENDERPATH_SOFT:
5312                 break;
5313         }
5314         GL_CullFace(GL_NONE);
5315 }
5316
5317 void R_ResetViewRendering3D(void)
5318 {
5319         DrawQ_Finish();
5320
5321         R_SetupView(true);
5322         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5323         GL_Color(1, 1, 1, 1);
5324         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5325         GL_BlendFunc(GL_ONE, GL_ZERO);
5326         GL_ScissorTest(true);
5327         GL_DepthMask(true);
5328         GL_DepthRange(0, 1);
5329         GL_DepthTest(true);
5330         GL_DepthFunc(GL_LEQUAL);
5331         R_EntityMatrix(&identitymatrix);
5332         R_Mesh_ResetTextureState();
5333         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5334         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5335         switch(vid.renderpath)
5336         {
5337         case RENDERPATH_GL11:
5338         case RENDERPATH_GL13:
5339         case RENDERPATH_GL20:
5340         case RENDERPATH_GLES1:
5341         case RENDERPATH_GLES2:
5342                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5343                 break;
5344         case RENDERPATH_D3D9:
5345         case RENDERPATH_D3D10:
5346         case RENDERPATH_D3D11:
5347         case RENDERPATH_SOFT:
5348                 break;
5349         }
5350         GL_CullFace(r_refdef.view.cullface_back);
5351 }
5352
5353 /*
5354 ================
5355 R_RenderView_UpdateViewVectors
5356 ================
5357 */
5358 static void R_RenderView_UpdateViewVectors(void)
5359 {
5360         // break apart the view matrix into vectors for various purposes
5361         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5362         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5363         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5364         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5365         // make an inverted copy of the view matrix for tracking sprites
5366         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5367 }
5368
5369 void R_RenderScene(void);
5370 void R_RenderWaterPlanes(void);
5371
5372 static void R_Water_StartFrame(void)
5373 {
5374         int i;
5375         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5376         r_waterstate_waterplane_t *p;
5377
5378         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5379                 return;
5380
5381         switch(vid.renderpath)
5382         {
5383         case RENDERPATH_GL20:
5384         case RENDERPATH_D3D9:
5385         case RENDERPATH_D3D10:
5386         case RENDERPATH_D3D11:
5387         case RENDERPATH_SOFT:
5388         case RENDERPATH_GLES2:
5389                 break;
5390         case RENDERPATH_GL11:
5391         case RENDERPATH_GL13:
5392         case RENDERPATH_GLES1:
5393                 return;
5394         }
5395
5396         // set waterwidth and waterheight to the water resolution that will be
5397         // used (often less than the screen resolution for faster rendering)
5398         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5399
5400         // calculate desired texture sizes
5401         // can't use water if the card does not support the texture size
5402         if (!r_water.integer || r_showsurfaces.integer)
5403                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5404         else if (vid.support.arb_texture_non_power_of_two)
5405         {
5406                 texturewidth = waterwidth;
5407                 textureheight = waterheight;
5408                 camerawidth = waterwidth;
5409                 cameraheight = waterheight;
5410         }
5411         else
5412         {
5413                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5414                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5415                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5416                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5417         }
5418
5419         // allocate textures as needed
5420         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5421         {
5422                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5423                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5424                 {
5425                         if (p->texture_refraction)
5426                                 R_FreeTexture(p->texture_refraction);
5427                         p->texture_refraction = NULL;
5428                         if (p->texture_reflection)
5429                                 R_FreeTexture(p->texture_reflection);
5430                         p->texture_reflection = NULL;
5431                         if (p->texture_camera)
5432                                 R_FreeTexture(p->texture_camera);
5433                         p->texture_camera = NULL;
5434                 }
5435                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5436                 r_waterstate.texturewidth = texturewidth;
5437                 r_waterstate.textureheight = textureheight;
5438                 r_waterstate.camerawidth = camerawidth;
5439                 r_waterstate.cameraheight = cameraheight;
5440         }
5441
5442         if (r_waterstate.texturewidth)
5443         {
5444                 int scaledwidth, scaledheight;
5445
5446                 r_waterstate.enabled = true;
5447
5448                 // when doing a reduced render (HDR) we want to use a smaller area
5449                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5450                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5451                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5452
5453                 // set up variables that will be used in shader setup
5454                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5455                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5456                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5457                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5458         }
5459
5460         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5461         r_waterstate.numwaterplanes = 0;
5462 }
5463
5464 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5465 {
5466         int triangleindex, planeindex;
5467         const int *e;
5468         vec3_t vert[3];
5469         vec3_t normal;
5470         vec3_t center;
5471         mplane_t plane;
5472         r_waterstate_waterplane_t *p;
5473         texture_t *t = R_GetCurrentTexture(surface->texture);
5474
5475         // just use the first triangle with a valid normal for any decisions
5476         VectorClear(normal);
5477         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5478         {
5479                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5480                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5481                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5482                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5483                 if (VectorLength2(normal) >= 0.001)
5484                         break;
5485         }
5486
5487         VectorCopy(normal, plane.normal);
5488         VectorNormalize(plane.normal);
5489         plane.dist = DotProduct(vert[0], plane.normal);
5490         PlaneClassify(&plane);
5491         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5492         {
5493                 // skip backfaces (except if nocullface is set)
5494                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5495                         return;
5496                 VectorNegate(plane.normal, plane.normal);
5497                 plane.dist *= -1;
5498                 PlaneClassify(&plane);
5499         }
5500
5501
5502         // find a matching plane if there is one
5503         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5504                 if(p->camera_entity == t->camera_entity)
5505                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5506                                 break;
5507         if (planeindex >= r_waterstate.maxwaterplanes)
5508                 return; // nothing we can do, out of planes
5509
5510         // if this triangle does not fit any known plane rendered this frame, add one
5511         if (planeindex >= r_waterstate.numwaterplanes)
5512         {
5513                 // store the new plane
5514                 r_waterstate.numwaterplanes++;
5515                 p->plane = plane;
5516                 // clear materialflags and pvs
5517                 p->materialflags = 0;
5518                 p->pvsvalid = false;
5519                 p->camera_entity = t->camera_entity;
5520                 VectorCopy(surface->mins, p->mins);
5521                 VectorCopy(surface->maxs, p->maxs);
5522         }
5523         else
5524         {
5525                 // merge mins/maxs
5526                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5527                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5528                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5529                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5530                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5531                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5532         }
5533         // merge this surface's materialflags into the waterplane
5534         p->materialflags |= t->currentmaterialflags;
5535         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5536         {
5537                 // merge this surface's PVS into the waterplane
5538                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5539                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5540                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5541                 {
5542                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5543                         p->pvsvalid = true;
5544                 }
5545         }
5546 }
5547
5548 static void R_Water_ProcessPlanes(void)
5549 {
5550         int myscissor[4];
5551         r_refdef_view_t originalview;
5552         r_refdef_view_t myview;
5553         int planeindex;
5554         r_waterstate_waterplane_t *p;
5555         vec3_t visorigin;
5556
5557         originalview = r_refdef.view;
5558
5559         // make sure enough textures are allocated
5560         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5561         {
5562                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5563                 {
5564                         if (!p->texture_refraction)
5565                                 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);
5566                         if (!p->texture_refraction)
5567                                 goto error;
5568                 }
5569                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5570                 {
5571                         if (!p->texture_camera)
5572                                 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);
5573                         if (!p->texture_camera)
5574                                 goto error;
5575                 }
5576
5577                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5578                 {
5579                         if (!p->texture_reflection)
5580                                 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);
5581                         if (!p->texture_reflection)
5582                                 goto error;
5583                 }
5584         }
5585
5586         // render views
5587         r_refdef.view = originalview;
5588         r_refdef.view.showdebug = false;
5589         r_refdef.view.width = r_waterstate.waterwidth;
5590         r_refdef.view.height = r_waterstate.waterheight;
5591         r_refdef.view.useclipplane = true;
5592         myview = r_refdef.view;
5593         r_waterstate.renderingscene = true;
5594         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5595         {
5596                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5597                 {
5598                         r_refdef.view = myview;
5599                         if(r_water_scissormode.integer)
5600                         {
5601                                 R_SetupView(true);
5602                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5603                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5604                         }
5605
5606                         // render reflected scene and copy into texture
5607                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5608                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5609                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5610                         r_refdef.view.clipplane = p->plane;
5611
5612                         // reverse the cullface settings for this render
5613                         r_refdef.view.cullface_front = GL_FRONT;
5614                         r_refdef.view.cullface_back = GL_BACK;
5615                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5616                         {
5617                                 r_refdef.view.usecustompvs = true;
5618                                 if (p->pvsvalid)
5619                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5620                                 else
5621                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5622                         }
5623
5624                         R_ResetViewRendering3D();
5625                         R_ClearScreen(r_refdef.fogenabled);
5626                         if(r_water_scissormode.integer & 2)
5627                                 R_View_UpdateWithScissor(myscissor);
5628                         else
5629                                 R_View_Update();
5630                         if(r_water_scissormode.integer & 1)
5631                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5632                         R_RenderScene();
5633
5634                         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);
5635                 }
5636
5637                 // render the normal view scene and copy into texture
5638                 // (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)
5639                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5640                 {
5641                         r_refdef.view = myview;
5642                         if(r_water_scissormode.integer)
5643                         {
5644                                 R_SetupView(true);
5645                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5646                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5647                         }
5648
5649                         r_waterstate.renderingrefraction = true;
5650
5651                         r_refdef.view.clipplane = p->plane;
5652                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5653                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5654
5655                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5656                         {
5657                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5658                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5659                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5660                                 R_RenderView_UpdateViewVectors();
5661                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5662                                 {
5663                                         r_refdef.view.usecustompvs = true;
5664                                         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);
5665                                 }
5666                         }
5667
5668                         PlaneClassify(&r_refdef.view.clipplane);
5669
5670                         R_ResetViewRendering3D();
5671                         R_ClearScreen(r_refdef.fogenabled);
5672                         if(r_water_scissormode.integer & 2)
5673                                 R_View_UpdateWithScissor(myscissor);
5674                         else
5675                                 R_View_Update();
5676                         if(r_water_scissormode.integer & 1)
5677                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5678                         R_RenderScene();
5679
5680                         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);
5681                         r_waterstate.renderingrefraction = false;
5682                 }
5683                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5684                 {
5685                         r_refdef.view = myview;
5686
5687                         r_refdef.view.clipplane = p->plane;
5688                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5689                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5690
5691                         r_refdef.view.width = r_waterstate.camerawidth;
5692                         r_refdef.view.height = r_waterstate.cameraheight;
5693                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5694                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5695
5696                         if(p->camera_entity)
5697                         {
5698                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5699                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5700                         }
5701
5702                         // note: all of the view is used for displaying... so
5703                         // there is no use in scissoring
5704
5705                         // reverse the cullface settings for this render
5706                         r_refdef.view.cullface_front = GL_FRONT;
5707                         r_refdef.view.cullface_back = GL_BACK;
5708                         // also reverse the view matrix
5709                         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
5710                         R_RenderView_UpdateViewVectors();
5711                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5712                         {
5713                                 r_refdef.view.usecustompvs = true;
5714                                 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);
5715                         }
5716                         
5717                         // camera needs no clipplane
5718                         r_refdef.view.useclipplane = false;
5719
5720                         PlaneClassify(&r_refdef.view.clipplane);
5721
5722                         R_ResetViewRendering3D();
5723                         R_ClearScreen(r_refdef.fogenabled);
5724                         R_View_Update();
5725                         R_RenderScene();
5726
5727                         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);
5728                         r_waterstate.renderingrefraction = false;
5729                 }
5730
5731         }
5732         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5733         r_waterstate.renderingscene = false;
5734         r_refdef.view = originalview;
5735         R_ResetViewRendering3D();
5736         R_ClearScreen(r_refdef.fogenabled);
5737         R_View_Update();
5738         return;
5739 error:
5740         r_refdef.view = originalview;
5741         r_waterstate.renderingscene = false;
5742         Cvar_SetValueQuick(&r_water, 0);
5743         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5744         return;
5745 }
5746
5747 void R_Bloom_StartFrame(void)
5748 {
5749         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5750         int viewwidth, viewheight;
5751         textype_t textype;
5752
5753         if (r_viewscale_fpsscaling.integer)
5754         {
5755                 double actualframetime;
5756                 double targetframetime;
5757                 double adjust;
5758                 actualframetime = r_refdef.lastdrawscreentime;
5759                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5760                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5761                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5762                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5763                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5764                 viewscalefpsadjusted += adjust;
5765                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5766         }
5767         else
5768                 viewscalefpsadjusted = 1.0f;
5769
5770         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5771
5772         switch(vid.renderpath)
5773         {
5774         case RENDERPATH_GL20:
5775         case RENDERPATH_D3D9:
5776         case RENDERPATH_D3D10:
5777         case RENDERPATH_D3D11:
5778         case RENDERPATH_SOFT:
5779         case RENDERPATH_GLES2:
5780                 break;
5781         case RENDERPATH_GL11:
5782         case RENDERPATH_GL13:
5783         case RENDERPATH_GLES1:
5784                 return;
5785         }
5786
5787         // set bloomwidth and bloomheight to the bloom resolution that will be
5788         // used (often less than the screen resolution for faster rendering)
5789         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5790         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5791         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5792         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5793         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5794
5795         // calculate desired texture sizes
5796         if (vid.support.arb_texture_non_power_of_two)
5797         {
5798                 screentexturewidth = vid.width;
5799                 screentextureheight = vid.height;
5800                 bloomtexturewidth = r_bloomstate.bloomwidth;
5801                 bloomtextureheight = r_bloomstate.bloomheight;
5802         }
5803         else
5804         {
5805                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5806                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5807                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5808                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5809         }
5810
5811         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))
5812         {
5813                 Cvar_SetValueQuick(&r_hdr, 0);
5814                 Cvar_SetValueQuick(&r_bloom, 0);
5815                 Cvar_SetValueQuick(&r_motionblur, 0);
5816                 Cvar_SetValueQuick(&r_damageblur, 0);
5817         }
5818
5819         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)
5820                 screentexturewidth = screentextureheight = 0;
5821         if (!r_hdr.integer && !r_bloom.integer)
5822                 bloomtexturewidth = bloomtextureheight = 0;
5823
5824         textype = TEXTYPE_COLORBUFFER;
5825         switch (vid.renderpath)
5826         {
5827         case RENDERPATH_GL20:
5828         case RENDERPATH_GLES2:
5829                 if (vid.support.ext_framebuffer_object)
5830                 {
5831                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5832                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5833                 }
5834                 break;
5835         case RENDERPATH_GL11:
5836         case RENDERPATH_GL13:
5837         case RENDERPATH_GLES1:
5838         case RENDERPATH_D3D9:
5839         case RENDERPATH_D3D10:
5840         case RENDERPATH_D3D11:
5841         case RENDERPATH_SOFT:
5842                 break;
5843         }
5844
5845         // allocate textures as needed
5846         if (r_bloomstate.screentexturewidth != screentexturewidth
5847          || r_bloomstate.screentextureheight != screentextureheight
5848          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5849          || r_bloomstate.bloomtextureheight != bloomtextureheight
5850          || r_bloomstate.texturetype != textype
5851          || r_bloomstate.viewfbo != r_viewfbo.integer)
5852         {
5853                 if (r_bloomstate.texture_bloom)
5854                         R_FreeTexture(r_bloomstate.texture_bloom);
5855                 r_bloomstate.texture_bloom = NULL;
5856                 if (r_bloomstate.texture_screen)
5857                         R_FreeTexture(r_bloomstate.texture_screen);
5858                 r_bloomstate.texture_screen = NULL;
5859                 if (r_bloomstate.fbo_framebuffer)
5860                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5861                 r_bloomstate.fbo_framebuffer = 0;
5862                 if (r_bloomstate.texture_framebuffercolor)
5863                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5864                 r_bloomstate.texture_framebuffercolor = NULL;
5865                 if (r_bloomstate.texture_framebufferdepth)
5866                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5867                 r_bloomstate.texture_framebufferdepth = NULL;
5868                 r_bloomstate.screentexturewidth = screentexturewidth;
5869                 r_bloomstate.screentextureheight = screentextureheight;
5870                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5871                         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);
5872                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5873                 {
5874                         // FIXME: choose depth bits based on a cvar
5875                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5876                         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);
5877                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5878                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5879                         // render depth into one texture and normalmap into the other
5880                         if (qglDrawBuffer)
5881                         {
5882                                 int status;
5883                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5884                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5885                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5886                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5887                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5888                         }
5889                 }
5890                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5891                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5892                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5893                         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);
5894                 r_bloomstate.viewfbo = r_viewfbo.integer;
5895                 r_bloomstate.texturetype = textype;
5896         }
5897
5898         // when doing a reduced render (HDR) we want to use a smaller area
5899         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5900         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5901         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5902         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5903         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5904
5905         // set up a texcoord array for the full resolution screen image
5906         // (we have to keep this around to copy back during final render)
5907         r_bloomstate.screentexcoord2f[0] = 0;
5908         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5909         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5910         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5911         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5912         r_bloomstate.screentexcoord2f[5] = 0;
5913         r_bloomstate.screentexcoord2f[6] = 0;
5914         r_bloomstate.screentexcoord2f[7] = 0;
5915
5916         // set up a texcoord array for the reduced resolution bloom image
5917         // (which will be additive blended over the screen image)
5918         r_bloomstate.bloomtexcoord2f[0] = 0;
5919         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5920         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5921         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5922         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5923         r_bloomstate.bloomtexcoord2f[5] = 0;
5924         r_bloomstate.bloomtexcoord2f[6] = 0;
5925         r_bloomstate.bloomtexcoord2f[7] = 0;
5926
5927         switch(vid.renderpath)
5928         {
5929         case RENDERPATH_GL11:
5930         case RENDERPATH_GL13:
5931         case RENDERPATH_GL20:
5932         case RENDERPATH_SOFT:
5933         case RENDERPATH_GLES1:
5934         case RENDERPATH_GLES2:
5935                 break;
5936         case RENDERPATH_D3D9:
5937         case RENDERPATH_D3D10:
5938         case RENDERPATH_D3D11:
5939                 {
5940                         int i;
5941                         for (i = 0;i < 4;i++)
5942                         {
5943                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5944                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5945                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5946                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5947                         }
5948                 }
5949                 break;
5950         }
5951
5952         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5953         {
5954                 r_bloomstate.enabled = true;
5955                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5956         }
5957
5958         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);
5959
5960         if (r_bloomstate.fbo_framebuffer)
5961                 r_refdef.view.clear = true;
5962 }
5963
5964 void R_Bloom_CopyBloomTexture(float colorscale)
5965 {
5966         r_refdef.stats.bloom++;
5967
5968         // scale down screen texture to the bloom texture size
5969         CHECKGLERROR
5970         R_Mesh_SetMainRenderTargets();
5971         R_SetViewport(&r_bloomstate.viewport);
5972         GL_BlendFunc(GL_ONE, GL_ZERO);
5973         GL_Color(colorscale, colorscale, colorscale, 1);
5974         // 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...
5975         switch(vid.renderpath)
5976         {
5977         case RENDERPATH_GL11:
5978         case RENDERPATH_GL13:
5979         case RENDERPATH_GL20:
5980         case RENDERPATH_GLES1:
5981         case RENDERPATH_GLES2:
5982         case RENDERPATH_SOFT:
5983                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5984                 break;
5985         case RENDERPATH_D3D9:
5986         case RENDERPATH_D3D10:
5987         case RENDERPATH_D3D11:
5988                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5989                 break;
5990         }
5991         // TODO: do boxfilter scale-down in shader?
5992         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5993         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5994         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5995
5996         // we now have a bloom image in the framebuffer
5997         // copy it into the bloom image texture for later processing
5998         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);
5999         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6000 }
6001
6002 void R_Bloom_CopyHDRTexture(void)
6003 {
6004         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);
6005         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6006 }
6007
6008 void R_Bloom_MakeTexture(void)
6009 {
6010         int x, range, dir;
6011         float xoffset, yoffset, r, brighten;
6012
6013         r_refdef.stats.bloom++;
6014
6015         R_ResetViewRendering2D();
6016
6017         // we have a bloom image in the framebuffer
6018         CHECKGLERROR
6019         R_SetViewport(&r_bloomstate.viewport);
6020
6021         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6022         {
6023                 x *= 2;
6024                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6025                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6026                 GL_Color(r,r,r,1);
6027                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6028                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6029                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6030                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6031
6032                 // copy the vertically blurred bloom view to a texture
6033                 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);
6034                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6035         }
6036
6037         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6038         brighten = r_bloom_brighten.value;
6039         if (r_bloomstate.hdr)
6040                 brighten *= r_hdr_range.value;
6041         brighten = sqrt(brighten);
6042         if(range >= 1)
6043                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6044         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6045
6046         for (dir = 0;dir < 2;dir++)
6047         {
6048                 // blend on at multiple vertical offsets to achieve a vertical blur
6049                 // TODO: do offset blends using GLSL
6050                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6051                 GL_BlendFunc(GL_ONE, GL_ZERO);
6052                 for (x = -range;x <= range;x++)
6053                 {
6054                         if (!dir){xoffset = 0;yoffset = x;}
6055                         else {xoffset = x;yoffset = 0;}
6056                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6057                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6058                         // compute a texcoord array with the specified x and y offset
6059                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6060                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6061                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6062                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6063                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6064                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6065                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6066                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6067                         // this r value looks like a 'dot' particle, fading sharply to
6068                         // black at the edges
6069                         // (probably not realistic but looks good enough)
6070                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6071                         //r = brighten/(range*2+1);
6072                         r = brighten / (range * 2 + 1);
6073                         if(range >= 1)
6074                                 r *= (1 - x*x/(float)(range*range));
6075                         GL_Color(r, r, r, 1);
6076                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6077                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6078                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6079                         GL_BlendFunc(GL_ONE, GL_ONE);
6080                 }
6081
6082                 // copy the vertically blurred bloom view to a texture
6083                 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);
6084                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6085         }
6086 }
6087
6088 void R_HDR_RenderBloomTexture(void)
6089 {
6090         int oldwidth, oldheight;
6091         float oldcolorscale;
6092         qboolean oldwaterstate;
6093
6094         oldwaterstate = r_waterstate.enabled;
6095         oldcolorscale = r_refdef.view.colorscale;
6096         oldwidth = r_refdef.view.width;
6097         oldheight = r_refdef.view.height;
6098         r_refdef.view.width = r_bloomstate.bloomwidth;
6099         r_refdef.view.height = r_bloomstate.bloomheight;
6100
6101         if(r_hdr.integer < 2)
6102                 r_waterstate.enabled = false;
6103
6104         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6105         // TODO: add exposure compensation features
6106         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6107
6108         r_refdef.view.showdebug = false;
6109         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6110
6111         R_ResetViewRendering3D();
6112
6113         R_ClearScreen(r_refdef.fogenabled);
6114         if (r_timereport_active)
6115                 R_TimeReport("HDRclear");
6116
6117         R_View_Update();
6118         if (r_timereport_active)
6119                 R_TimeReport("visibility");
6120
6121         // only do secondary renders with HDR if r_hdr is 2 or higher
6122         r_waterstate.numwaterplanes = 0;
6123         if (r_waterstate.enabled)
6124                 R_RenderWaterPlanes();
6125
6126         r_refdef.view.showdebug = true;
6127         R_RenderScene();
6128         r_waterstate.numwaterplanes = 0;
6129
6130         R_ResetViewRendering2D();
6131
6132         R_Bloom_CopyHDRTexture();
6133         R_Bloom_MakeTexture();
6134
6135         // restore the view settings
6136         r_waterstate.enabled = oldwaterstate;
6137         r_refdef.view.width = oldwidth;
6138         r_refdef.view.height = oldheight;
6139         r_refdef.view.colorscale = oldcolorscale;
6140
6141         R_ResetViewRendering3D();
6142
6143         R_ClearScreen(r_refdef.fogenabled);
6144         if (r_timereport_active)
6145                 R_TimeReport("viewclear");
6146 }
6147
6148 static void R_BlendView(void)
6149 {
6150         unsigned int permutation;
6151         float uservecs[4][4];
6152
6153         switch (vid.renderpath)
6154         {
6155         case RENDERPATH_GL20:
6156         case RENDERPATH_D3D9:
6157         case RENDERPATH_D3D10:
6158         case RENDERPATH_D3D11:
6159         case RENDERPATH_SOFT:
6160         case RENDERPATH_GLES2:
6161                 permutation =
6162                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6163                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6164                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6165                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6166                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6167
6168                 if (r_bloomstate.texture_screen)
6169                 {
6170                         // make sure the buffer is available
6171                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6172
6173                         R_ResetViewRendering2D();
6174                         R_Mesh_SetMainRenderTargets();
6175
6176                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6177                         {
6178                                 // declare variables
6179                                 float speed;
6180                                 static float avgspeed;
6181
6182                                 speed = VectorLength(cl.movement_velocity);
6183
6184                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6185                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6186
6187                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6188                                 speed = bound(0, speed, 1);
6189                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6190
6191                                 // calculate values into a standard alpha
6192                                 cl.motionbluralpha = 1 - exp(-
6193                                                 (
6194                                                  (r_motionblur.value * speed / 80)
6195                                                  +
6196                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6197                                                 )
6198                                                 /
6199                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6200                                            );
6201
6202                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6203                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6204                                 // apply the blur
6205                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6206                                 {
6207                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6208                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6209                                         switch(vid.renderpath)
6210                                         {
6211                                         case RENDERPATH_GL11:
6212                                         case RENDERPATH_GL13:
6213                                         case RENDERPATH_GL20:
6214                                         case RENDERPATH_GLES1:
6215                                         case RENDERPATH_GLES2:
6216                                         case RENDERPATH_SOFT:
6217                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6218                                                 break;
6219                                         case RENDERPATH_D3D9:
6220                                         case RENDERPATH_D3D10:
6221                                         case RENDERPATH_D3D11:
6222                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6223                                                 break;
6224                                         }
6225                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6226                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6227                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6228                                 }
6229                         }
6230
6231                         // copy view into the screen texture
6232                         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);
6233                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6234                 }
6235                 else if (!r_bloomstate.texture_bloom)
6236                 {
6237                         // we may still have to do view tint...
6238                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6239                         {
6240                                 // apply a color tint to the whole view
6241                                 R_ResetViewRendering2D();
6242                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6243                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6244                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6245                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6246                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6247                         }
6248                         break; // no screen processing, no bloom, skip it
6249                 }
6250
6251                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6252                 {
6253                         // render simple bloom effect
6254                         // copy the screen and shrink it and darken it for the bloom process
6255                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6256                         // make the bloom texture
6257                         R_Bloom_MakeTexture();
6258                 }
6259
6260 #if _MSC_VER >= 1400
6261 #define sscanf sscanf_s
6262 #endif
6263                 memset(uservecs, 0, sizeof(uservecs));
6264                 if (r_glsl_postprocess_uservec1_enable.integer)
6265                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6266                 if (r_glsl_postprocess_uservec2_enable.integer)
6267                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6268                 if (r_glsl_postprocess_uservec3_enable.integer)
6269                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6270                 if (r_glsl_postprocess_uservec4_enable.integer)
6271                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6272
6273                 R_ResetViewRendering2D();
6274                 GL_Color(1, 1, 1, 1);
6275                 GL_BlendFunc(GL_ONE, GL_ZERO);
6276
6277                 switch(vid.renderpath)
6278                 {
6279                 case RENDERPATH_GL20:
6280                 case RENDERPATH_GLES2:
6281                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6282                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6283                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6284                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6285                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6286                         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]);
6287                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6288                         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]);
6289                         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]);
6290                         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]);
6291                         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]);
6292                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6293                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6294                         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);
6295                         break;
6296                 case RENDERPATH_D3D9:
6297 #ifdef SUPPORTD3D
6298                         // 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...
6299                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6300                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6301                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6302                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6303                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6304                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6305                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6306                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6307                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6308                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6309                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6310                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6311                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6312                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6313 #endif
6314                         break;
6315                 case RENDERPATH_D3D10:
6316                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6317                         break;
6318                 case RENDERPATH_D3D11:
6319                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6320                         break;
6321                 case RENDERPATH_SOFT:
6322                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6323                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6324                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6325                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6326                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6327                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6328                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6329                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6330                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6331                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6332                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6333                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6334                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6335                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6336                         break;
6337                 default:
6338                         break;
6339                 }
6340                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6341                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6342                 break;
6343         case RENDERPATH_GL11:
6344         case RENDERPATH_GL13:
6345         case RENDERPATH_GLES1:
6346                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6347                 {
6348                         // apply a color tint to the whole view
6349                         R_ResetViewRendering2D();
6350                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6351                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6352                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6353                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6354                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6355                 }
6356                 break;
6357         }
6358 }
6359
6360 matrix4x4_t r_waterscrollmatrix;
6361
6362 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6363 {
6364         if (r_refdef.fog_density)
6365         {
6366                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6367                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6368                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6369
6370                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6371                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6372                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6373                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6374
6375                 {
6376                         vec3_t fogvec;
6377                         VectorCopy(r_refdef.fogcolor, fogvec);
6378                         //   color.rgb *= ContrastBoost * SceneBrightness;
6379                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6380                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6381                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6382                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6383                 }
6384         }
6385 }
6386
6387 void R_UpdateVariables(void)
6388 {
6389         R_Textures_Frame();
6390
6391         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6392
6393         r_refdef.farclip = r_farclip_base.value;
6394         if (r_refdef.scene.worldmodel)
6395                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6396         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6397
6398         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6399                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6400         r_refdef.polygonfactor = 0;
6401         r_refdef.polygonoffset = 0;
6402         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6403         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6404
6405         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6406         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6407         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6408         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6409         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6410         if (FAKELIGHT_ENABLED)
6411         {
6412                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6413         }
6414         if (r_showsurfaces.integer)
6415         {
6416                 r_refdef.scene.rtworld = false;
6417                 r_refdef.scene.rtworldshadows = false;
6418                 r_refdef.scene.rtdlight = false;
6419                 r_refdef.scene.rtdlightshadows = false;
6420                 r_refdef.lightmapintensity = 0;
6421         }
6422
6423         if (gamemode == GAME_NEHAHRA)
6424         {
6425                 if (gl_fogenable.integer)
6426                 {
6427                         r_refdef.oldgl_fogenable = true;
6428                         r_refdef.fog_density = gl_fogdensity.value;
6429                         r_refdef.fog_red = gl_fogred.value;
6430                         r_refdef.fog_green = gl_foggreen.value;
6431                         r_refdef.fog_blue = gl_fogblue.value;
6432                         r_refdef.fog_alpha = 1;
6433                         r_refdef.fog_start = 0;
6434                         r_refdef.fog_end = gl_skyclip.value;
6435                         r_refdef.fog_height = 1<<30;
6436                         r_refdef.fog_fadedepth = 128;
6437                 }
6438                 else if (r_refdef.oldgl_fogenable)
6439                 {
6440                         r_refdef.oldgl_fogenable = false;
6441                         r_refdef.fog_density = 0;
6442                         r_refdef.fog_red = 0;
6443                         r_refdef.fog_green = 0;
6444                         r_refdef.fog_blue = 0;
6445                         r_refdef.fog_alpha = 0;
6446                         r_refdef.fog_start = 0;
6447                         r_refdef.fog_end = 0;
6448                         r_refdef.fog_height = 1<<30;
6449                         r_refdef.fog_fadedepth = 128;
6450                 }
6451         }
6452
6453         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6454         r_refdef.fog_start = max(0, r_refdef.fog_start);
6455         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6456
6457         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6458
6459         if (r_refdef.fog_density && r_drawfog.integer)
6460         {
6461                 r_refdef.fogenabled = true;
6462                 // this is the point where the fog reaches 0.9986 alpha, which we
6463                 // consider a good enough cutoff point for the texture
6464                 // (0.9986 * 256 == 255.6)
6465                 if (r_fog_exp2.integer)
6466                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6467                 else
6468                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6469                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6470                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6471                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6472                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6473                         R_BuildFogHeightTexture();
6474                 // fog color was already set
6475                 // update the fog texture
6476                 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)
6477                         R_BuildFogTexture();
6478                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6479                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6480         }
6481         else
6482                 r_refdef.fogenabled = false;
6483
6484         switch(vid.renderpath)
6485         {
6486         case RENDERPATH_GL20:
6487         case RENDERPATH_D3D9:
6488         case RENDERPATH_D3D10:
6489         case RENDERPATH_D3D11:
6490         case RENDERPATH_SOFT:
6491         case RENDERPATH_GLES2:
6492                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6493                 {
6494                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6495                         {
6496                                 // build GLSL gamma texture
6497 #define RAMPWIDTH 256
6498                                 unsigned short ramp[RAMPWIDTH * 3];
6499                                 unsigned char rampbgr[RAMPWIDTH][4];
6500                                 int i;
6501
6502                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6503
6504                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6505                                 for(i = 0; i < RAMPWIDTH; ++i)
6506                                 {
6507                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6508                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6509                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6510                                         rampbgr[i][3] = 0;
6511                                 }
6512                                 if (r_texture_gammaramps)
6513                                 {
6514                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6515                                 }
6516                                 else
6517                                 {
6518                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6519                                 }
6520                         }
6521                 }
6522                 else
6523                 {
6524                         // remove GLSL gamma texture
6525                 }
6526                 break;
6527         case RENDERPATH_GL11:
6528         case RENDERPATH_GL13:
6529         case RENDERPATH_GLES1:
6530                 break;
6531         }
6532 }
6533
6534 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6535 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6536 /*
6537 ================
6538 R_SelectScene
6539 ================
6540 */
6541 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6542         if( scenetype != r_currentscenetype ) {
6543                 // store the old scenetype
6544                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6545                 r_currentscenetype = scenetype;
6546                 // move in the new scene
6547                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6548         }
6549 }
6550
6551 /*
6552 ================
6553 R_GetScenePointer
6554 ================
6555 */
6556 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6557 {
6558         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6559         if( scenetype == r_currentscenetype ) {
6560                 return &r_refdef.scene;
6561         } else {
6562                 return &r_scenes_store[ scenetype ];
6563         }
6564 }
6565
6566 /*
6567 ================
6568 R_RenderView
6569 ================
6570 */
6571 int dpsoftrast_test;
6572 void R_RenderView(void)
6573 {
6574         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6575
6576         dpsoftrast_test = r_test.integer;
6577
6578         if (r_timereport_active)
6579                 R_TimeReport("start");
6580         r_textureframe++; // used only by R_GetCurrentTexture
6581         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6582
6583         if(R_CompileShader_CheckStaticParms())
6584                 R_GLSL_Restart_f();
6585
6586         if (!r_drawentities.integer)
6587                 r_refdef.scene.numentities = 0;
6588
6589         R_AnimCache_ClearCache();
6590         R_FrameData_NewFrame();
6591
6592         /* adjust for stereo display */
6593         if(R_Stereo_Active())
6594         {
6595                 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);
6596                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6597         }
6598
6599         if (r_refdef.view.isoverlay)
6600         {
6601                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6602                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6603                 R_TimeReport("depthclear");
6604
6605                 r_refdef.view.showdebug = false;
6606
6607                 r_waterstate.enabled = false;
6608                 r_waterstate.numwaterplanes = 0;
6609
6610                 R_RenderScene();
6611
6612                 r_refdef.view.matrix = originalmatrix;
6613
6614                 CHECKGLERROR
6615                 return;
6616         }
6617
6618         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6619         {
6620                 r_refdef.view.matrix = originalmatrix;
6621                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6622         }
6623
6624         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6625
6626         R_RenderView_UpdateViewVectors();
6627
6628         R_Shadow_UpdateWorldLightSelection();
6629
6630         R_Bloom_StartFrame();
6631         R_Water_StartFrame();
6632
6633         CHECKGLERROR
6634         if (r_timereport_active)
6635                 R_TimeReport("viewsetup");
6636
6637         R_ResetViewRendering3D();
6638
6639         if (r_refdef.view.clear || r_refdef.fogenabled)
6640         {
6641                 R_ClearScreen(r_refdef.fogenabled);
6642                 if (r_timereport_active)
6643                         R_TimeReport("viewclear");
6644         }
6645         r_refdef.view.clear = true;
6646
6647         // this produces a bloom texture to be used in R_BlendView() later
6648         if (r_bloomstate.hdr)
6649         {
6650                 R_HDR_RenderBloomTexture();
6651                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6652                 r_textureframe++; // used only by R_GetCurrentTexture
6653         }
6654
6655         r_refdef.view.showdebug = true;
6656
6657         R_View_Update();
6658         if (r_timereport_active)
6659                 R_TimeReport("visibility");
6660
6661         r_waterstate.numwaterplanes = 0;
6662         if (r_waterstate.enabled)
6663                 R_RenderWaterPlanes();
6664
6665         R_RenderScene();
6666         r_waterstate.numwaterplanes = 0;
6667
6668         R_BlendView();
6669         if (r_timereport_active)
6670                 R_TimeReport("blendview");
6671
6672         GL_Scissor(0, 0, vid.width, vid.height);
6673         GL_ScissorTest(false);
6674
6675         r_refdef.view.matrix = originalmatrix;
6676
6677         CHECKGLERROR
6678 }
6679
6680 void R_RenderWaterPlanes(void)
6681 {
6682         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6683         {
6684                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6685                 if (r_timereport_active)
6686                         R_TimeReport("waterworld");
6687         }
6688
6689         // don't let sound skip if going slow
6690         if (r_refdef.scene.extraupdate)
6691                 S_ExtraUpdate ();
6692
6693         R_DrawModelsAddWaterPlanes();
6694         if (r_timereport_active)
6695                 R_TimeReport("watermodels");
6696
6697         if (r_waterstate.numwaterplanes)
6698         {
6699                 R_Water_ProcessPlanes();
6700                 if (r_timereport_active)
6701                         R_TimeReport("waterscenes");
6702         }
6703 }
6704
6705 extern void R_DrawLightningBeams (void);
6706 extern void VM_CL_AddPolygonsToMeshQueue (void);
6707 extern void R_DrawPortals (void);
6708 extern cvar_t cl_locs_show;
6709 static void R_DrawLocs(void);
6710 static void R_DrawEntityBBoxes(void);
6711 static void R_DrawModelDecals(void);
6712 extern void R_DrawModelShadows(void);
6713 extern void R_DrawModelShadowMaps(void);
6714 extern cvar_t cl_decals_newsystem;
6715 extern qboolean r_shadow_usingdeferredprepass;
6716 void R_RenderScene(void)
6717 {
6718         qboolean shadowmapping = false;
6719
6720         if (r_timereport_active)
6721                 R_TimeReport("beginscene");
6722
6723         r_refdef.stats.renders++;
6724
6725         R_UpdateFogColor();
6726
6727         // don't let sound skip if going slow
6728         if (r_refdef.scene.extraupdate)
6729                 S_ExtraUpdate ();
6730
6731         R_MeshQueue_BeginScene();
6732
6733         R_SkyStartFrame();
6734
6735         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);
6736
6737         if (r_timereport_active)
6738                 R_TimeReport("skystartframe");
6739
6740         if (cl.csqc_vidvars.drawworld)
6741         {
6742                 // don't let sound skip if going slow
6743                 if (r_refdef.scene.extraupdate)
6744                         S_ExtraUpdate ();
6745
6746                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6747                 {
6748                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6749                         if (r_timereport_active)
6750                                 R_TimeReport("worldsky");
6751                 }
6752
6753                 if (R_DrawBrushModelsSky() && r_timereport_active)
6754                         R_TimeReport("bmodelsky");
6755
6756                 if (skyrendermasked && skyrenderlater)
6757                 {
6758                         // we have to force off the water clipping plane while rendering sky
6759                         R_SetupView(false);
6760                         R_Sky();
6761                         R_SetupView(true);
6762                         if (r_timereport_active)
6763                                 R_TimeReport("sky");
6764                 }
6765         }
6766
6767         R_AnimCache_CacheVisibleEntities();
6768         if (r_timereport_active)
6769                 R_TimeReport("animation");
6770
6771         R_Shadow_PrepareLights();
6772         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6773                 R_Shadow_PrepareModelShadows();
6774         if (r_timereport_active)
6775                 R_TimeReport("preparelights");
6776
6777         if (R_Shadow_ShadowMappingEnabled())
6778                 shadowmapping = true;
6779
6780         if (r_shadow_usingdeferredprepass)
6781                 R_Shadow_DrawPrepass();
6782
6783         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6784         {
6785                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6786                 if (r_timereport_active)
6787                         R_TimeReport("worlddepth");
6788         }
6789         if (r_depthfirst.integer >= 2)
6790         {
6791                 R_DrawModelsDepth();
6792                 if (r_timereport_active)
6793                         R_TimeReport("modeldepth");
6794         }
6795
6796         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6797         {
6798                 R_DrawModelShadowMaps();
6799                 R_ResetViewRendering3D();
6800                 // don't let sound skip if going slow
6801                 if (r_refdef.scene.extraupdate)
6802                         S_ExtraUpdate ();
6803         }
6804
6805         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6806         {
6807                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6808                 if (r_timereport_active)
6809                         R_TimeReport("world");
6810         }
6811
6812         // don't let sound skip if going slow
6813         if (r_refdef.scene.extraupdate)
6814                 S_ExtraUpdate ();
6815
6816         R_DrawModels();
6817         if (r_timereport_active)
6818                 R_TimeReport("models");
6819
6820         // don't let sound skip if going slow
6821         if (r_refdef.scene.extraupdate)
6822                 S_ExtraUpdate ();
6823
6824         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6825         {
6826                 R_DrawModelShadows();
6827                 R_ResetViewRendering3D();
6828                 // don't let sound skip if going slow
6829                 if (r_refdef.scene.extraupdate)
6830                         S_ExtraUpdate ();
6831         }
6832
6833         if (!r_shadow_usingdeferredprepass)
6834         {
6835                 R_Shadow_DrawLights();
6836                 if (r_timereport_active)
6837                         R_TimeReport("rtlights");
6838         }
6839
6840         // don't let sound skip if going slow
6841         if (r_refdef.scene.extraupdate)
6842                 S_ExtraUpdate ();
6843
6844         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6845         {
6846                 R_DrawModelShadows();
6847                 R_ResetViewRendering3D();
6848                 // don't let sound skip if going slow
6849                 if (r_refdef.scene.extraupdate)
6850                         S_ExtraUpdate ();
6851         }
6852
6853         if (cl.csqc_vidvars.drawworld)
6854         {
6855                 if (cl_decals_newsystem.integer)
6856                 {
6857                         R_DrawModelDecals();
6858                         if (r_timereport_active)
6859                                 R_TimeReport("modeldecals");
6860                 }
6861                 else
6862                 {
6863                         R_DrawDecals();
6864                         if (r_timereport_active)
6865                                 R_TimeReport("decals");
6866                 }
6867
6868                 R_DrawParticles();
6869                 if (r_timereport_active)
6870                         R_TimeReport("particles");
6871
6872                 R_DrawExplosions();
6873                 if (r_timereport_active)
6874                         R_TimeReport("explosions");
6875
6876                 R_DrawLightningBeams();
6877                 if (r_timereport_active)
6878                         R_TimeReport("lightning");
6879         }
6880
6881         VM_CL_AddPolygonsToMeshQueue();
6882
6883         if (r_refdef.view.showdebug)
6884         {
6885                 if (cl_locs_show.integer)
6886                 {
6887                         R_DrawLocs();
6888                         if (r_timereport_active)
6889                                 R_TimeReport("showlocs");
6890                 }
6891
6892                 if (r_drawportals.integer)
6893                 {
6894                         R_DrawPortals();
6895                         if (r_timereport_active)
6896                                 R_TimeReport("portals");
6897                 }
6898
6899                 if (r_showbboxes.value > 0)
6900                 {
6901                         R_DrawEntityBBoxes();
6902                         if (r_timereport_active)
6903                                 R_TimeReport("bboxes");
6904                 }
6905         }
6906
6907         if (r_transparent.integer)
6908         {
6909                 R_MeshQueue_RenderTransparent();
6910                 if (r_timereport_active)
6911                         R_TimeReport("drawtrans");
6912         }
6913
6914         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))
6915         {
6916                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6917                 if (r_timereport_active)
6918                         R_TimeReport("worlddebug");
6919                 R_DrawModelsDebug();
6920                 if (r_timereport_active)
6921                         R_TimeReport("modeldebug");
6922         }
6923
6924         if (cl.csqc_vidvars.drawworld)
6925         {
6926                 R_Shadow_DrawCoronas();
6927                 if (r_timereport_active)
6928                         R_TimeReport("coronas");
6929         }
6930
6931 #if 0
6932         {
6933                 GL_DepthTest(false);
6934                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6935                 GL_Color(1, 1, 1, 1);
6936                 qglBegin(GL_POLYGON);
6937                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6938                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6939                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6940                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6941                 qglEnd();
6942                 qglBegin(GL_POLYGON);
6943                 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]);
6944                 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]);
6945                 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]);
6946                 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]);
6947                 qglEnd();
6948                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6949         }
6950 #endif
6951
6952         // don't let sound skip if going slow
6953         if (r_refdef.scene.extraupdate)
6954                 S_ExtraUpdate ();
6955
6956         R_ResetViewRendering2D();
6957 }
6958
6959 static const unsigned short bboxelements[36] =
6960 {
6961         5, 1, 3, 5, 3, 7,
6962         6, 2, 0, 6, 0, 4,
6963         7, 3, 2, 7, 2, 6,
6964         4, 0, 1, 4, 1, 5,
6965         4, 5, 7, 4, 7, 6,
6966         1, 0, 2, 1, 2, 3,
6967 };
6968
6969 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6970 {
6971         int i;
6972         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6973
6974         RSurf_ActiveWorldEntity();
6975
6976         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6977         GL_DepthMask(false);
6978         GL_DepthRange(0, 1);
6979         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6980 //      R_Mesh_ResetTextureState();
6981
6982         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6983         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6984         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6985         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6986         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6987         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6988         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6989         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6990         R_FillColors(color4f, 8, cr, cg, cb, ca);
6991         if (r_refdef.fogenabled)
6992         {
6993                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6994                 {
6995                         f1 = RSurf_FogVertex(v);
6996                         f2 = 1 - f1;
6997                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6998                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6999                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7000                 }
7001         }
7002         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7003         R_Mesh_ResetTextureState();
7004         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7005         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7006 }
7007
7008 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7009 {
7010         int i;
7011         float color[4];
7012         prvm_edict_t *edict;
7013         prvm_prog_t *prog_save = prog;
7014
7015         // this function draws bounding boxes of server entities
7016         if (!sv.active)
7017                 return;
7018
7019         GL_CullFace(GL_NONE);
7020         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7021
7022         prog = 0;
7023         SV_VM_Begin();
7024         for (i = 0;i < numsurfaces;i++)
7025         {
7026                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7027                 switch ((int)edict->fields.server->solid)
7028                 {
7029                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7030                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7031                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7032                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7033                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7034                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7035                 }
7036                 color[3] *= r_showbboxes.value;
7037                 color[3] = bound(0, color[3], 1);
7038                 GL_DepthTest(!r_showdisabledepthtest.integer);
7039                 GL_CullFace(r_refdef.view.cullface_front);
7040                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7041         }
7042         SV_VM_End();
7043         prog = prog_save;
7044 }
7045
7046 static void R_DrawEntityBBoxes(void)
7047 {
7048         int i;
7049         prvm_edict_t *edict;
7050         vec3_t center;
7051         prvm_prog_t *prog_save = prog;
7052
7053         // this function draws bounding boxes of server entities
7054         if (!sv.active)
7055                 return;
7056
7057         prog = 0;
7058         SV_VM_Begin();
7059         for (i = 0;i < prog->num_edicts;i++)
7060         {
7061                 edict = PRVM_EDICT_NUM(i);
7062                 if (edict->priv.server->free)
7063                         continue;
7064                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7065                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7066                         continue;
7067                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7068                         continue;
7069                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7070                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7071         }
7072         SV_VM_End();
7073         prog = prog_save;
7074 }
7075
7076 static const int nomodelelement3i[24] =
7077 {
7078         5, 2, 0,
7079         5, 1, 2,
7080         5, 0, 3,
7081         5, 3, 1,
7082         0, 2, 4,
7083         2, 1, 4,
7084         3, 0, 4,
7085         1, 3, 4
7086 };
7087
7088 static const unsigned short nomodelelement3s[24] =
7089 {
7090         5, 2, 0,
7091         5, 1, 2,
7092         5, 0, 3,
7093         5, 3, 1,
7094         0, 2, 4,
7095         2, 1, 4,
7096         3, 0, 4,
7097         1, 3, 4
7098 };
7099
7100 static const float nomodelvertex3f[6*3] =
7101 {
7102         -16,   0,   0,
7103          16,   0,   0,
7104           0, -16,   0,
7105           0,  16,   0,
7106           0,   0, -16,
7107           0,   0,  16
7108 };
7109
7110 static const float nomodelcolor4f[6*4] =
7111 {
7112         0.0f, 0.0f, 0.5f, 1.0f,
7113         0.0f, 0.0f, 0.5f, 1.0f,
7114         0.0f, 0.5f, 0.0f, 1.0f,
7115         0.0f, 0.5f, 0.0f, 1.0f,
7116         0.5f, 0.0f, 0.0f, 1.0f,
7117         0.5f, 0.0f, 0.0f, 1.0f
7118 };
7119
7120 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7121 {
7122         int i;
7123         float f1, f2, *c;
7124         float color4f[6*4];
7125
7126         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);
7127
7128         // this is only called once per entity so numsurfaces is always 1, and
7129         // surfacelist is always {0}, so this code does not handle batches
7130
7131         if (rsurface.ent_flags & RENDER_ADDITIVE)
7132         {
7133                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7134                 GL_DepthMask(false);
7135         }
7136         else if (rsurface.colormod[3] < 1)
7137         {
7138                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7139                 GL_DepthMask(false);
7140         }
7141         else
7142         {
7143                 GL_BlendFunc(GL_ONE, GL_ZERO);
7144                 GL_DepthMask(true);
7145         }
7146         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7147         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7148         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7149         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7150         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7151         for (i = 0, c = color4f;i < 6;i++, c += 4)
7152         {
7153                 c[0] *= rsurface.colormod[0];
7154                 c[1] *= rsurface.colormod[1];
7155                 c[2] *= rsurface.colormod[2];
7156                 c[3] *= rsurface.colormod[3];
7157         }
7158         if (r_refdef.fogenabled)
7159         {
7160                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7161                 {
7162                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7163                         f2 = 1 - f1;
7164                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7165                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7166                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7167                 }
7168         }
7169 //      R_Mesh_ResetTextureState();
7170         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7171         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7172         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7173 }
7174
7175 void R_DrawNoModel(entity_render_t *ent)
7176 {
7177         vec3_t org;
7178         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7179         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7180                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7181         else
7182                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7183 }
7184
7185 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7186 {
7187         vec3_t right1, right2, diff, normal;
7188
7189         VectorSubtract (org2, org1, normal);
7190
7191         // calculate 'right' vector for start
7192         VectorSubtract (r_refdef.view.origin, org1, diff);
7193         CrossProduct (normal, diff, right1);
7194         VectorNormalize (right1);
7195
7196         // calculate 'right' vector for end
7197         VectorSubtract (r_refdef.view.origin, org2, diff);
7198         CrossProduct (normal, diff, right2);
7199         VectorNormalize (right2);
7200
7201         vert[ 0] = org1[0] + width * right1[0];
7202         vert[ 1] = org1[1] + width * right1[1];
7203         vert[ 2] = org1[2] + width * right1[2];
7204         vert[ 3] = org1[0] - width * right1[0];
7205         vert[ 4] = org1[1] - width * right1[1];
7206         vert[ 5] = org1[2] - width * right1[2];
7207         vert[ 6] = org2[0] - width * right2[0];
7208         vert[ 7] = org2[1] - width * right2[1];
7209         vert[ 8] = org2[2] - width * right2[2];
7210         vert[ 9] = org2[0] + width * right2[0];
7211         vert[10] = org2[1] + width * right2[1];
7212         vert[11] = org2[2] + width * right2[2];
7213 }
7214
7215 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)
7216 {
7217         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7218         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7219         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7220         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7221         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7222         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7223         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7224         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7225         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7226         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7227         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7228         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7229 }
7230
7231 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7232 {
7233         int i;
7234         float *vertex3f;
7235         float v[3];
7236         VectorSet(v, x, y, z);
7237         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7238                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7239                         break;
7240         if (i == mesh->numvertices)
7241         {
7242                 if (mesh->numvertices < mesh->maxvertices)
7243                 {
7244                         VectorCopy(v, vertex3f);
7245                         mesh->numvertices++;
7246                 }
7247                 return mesh->numvertices;
7248         }
7249         else
7250                 return i;
7251 }
7252
7253 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7254 {
7255         int i;
7256         int *e, element[3];
7257         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7258         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7259         e = mesh->element3i + mesh->numtriangles * 3;
7260         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7261         {
7262                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7263                 if (mesh->numtriangles < mesh->maxtriangles)
7264                 {
7265                         *e++ = element[0];
7266                         *e++ = element[1];
7267                         *e++ = element[2];
7268                         mesh->numtriangles++;
7269                 }
7270                 element[1] = element[2];
7271         }
7272 }
7273
7274 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7275 {
7276         int i;
7277         int *e, element[3];
7278         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7279         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7280         e = mesh->element3i + mesh->numtriangles * 3;
7281         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7282         {
7283                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7284                 if (mesh->numtriangles < mesh->maxtriangles)
7285                 {
7286                         *e++ = element[0];
7287                         *e++ = element[1];
7288                         *e++ = element[2];
7289                         mesh->numtriangles++;
7290                 }
7291                 element[1] = element[2];
7292         }
7293 }
7294
7295 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7296 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7297 {
7298         int planenum, planenum2;
7299         int w;
7300         int tempnumpoints;
7301         mplane_t *plane, *plane2;
7302         double maxdist;
7303         double temppoints[2][256*3];
7304         // figure out how large a bounding box we need to properly compute this brush
7305         maxdist = 0;
7306         for (w = 0;w < numplanes;w++)
7307                 maxdist = max(maxdist, fabs(planes[w].dist));
7308         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7309         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7310         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7311         {
7312                 w = 0;
7313                 tempnumpoints = 4;
7314                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7315                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7316                 {
7317                         if (planenum2 == planenum)
7318                                 continue;
7319                         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);
7320                         w = !w;
7321                 }
7322                 if (tempnumpoints < 3)
7323                         continue;
7324                 // generate elements forming a triangle fan for this polygon
7325                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7326         }
7327 }
7328
7329 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)
7330 {
7331         texturelayer_t *layer;
7332         layer = t->currentlayers + t->currentnumlayers++;
7333         layer->type = type;
7334         layer->depthmask = depthmask;
7335         layer->blendfunc1 = blendfunc1;
7336         layer->blendfunc2 = blendfunc2;
7337         layer->texture = texture;
7338         layer->texmatrix = *matrix;
7339         layer->color[0] = r;
7340         layer->color[1] = g;
7341         layer->color[2] = b;
7342         layer->color[3] = a;
7343 }
7344
7345 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7346 {
7347         if(parms[0] == 0 && parms[1] == 0)
7348                 return false;
7349         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7350                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7351                         return false;
7352         return true;
7353 }
7354
7355 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7356 {
7357         double index, f;
7358         index = parms[2] + r_refdef.scene.time * parms[3];
7359         index -= floor(index);
7360         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7361         {
7362         default:
7363         case Q3WAVEFUNC_NONE:
7364         case Q3WAVEFUNC_NOISE:
7365         case Q3WAVEFUNC_COUNT:
7366                 f = 0;
7367                 break;
7368         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7369         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7370         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7371         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7372         case Q3WAVEFUNC_TRIANGLE:
7373                 index *= 4;
7374                 f = index - floor(index);
7375                 if (index < 1)
7376                         f = f;
7377                 else if (index < 2)
7378                         f = 1 - f;
7379                 else if (index < 3)
7380                         f = -f;
7381                 else
7382                         f = -(1 - f);
7383                 break;
7384         }
7385         f = parms[0] + parms[1] * f;
7386         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7387                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7388         return (float) f;
7389 }
7390
7391 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7392 {
7393         int w, h, idx;
7394         float f;
7395         float tcmat[12];
7396         matrix4x4_t matrix, temp;
7397         switch(tcmod->tcmod)
7398         {
7399                 case Q3TCMOD_COUNT:
7400                 case Q3TCMOD_NONE:
7401                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7402                                 matrix = r_waterscrollmatrix;
7403                         else
7404                                 matrix = identitymatrix;
7405                         break;
7406                 case Q3TCMOD_ENTITYTRANSLATE:
7407                         // this is used in Q3 to allow the gamecode to control texcoord
7408                         // scrolling on the entity, which is not supported in darkplaces yet.
7409                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7410                         break;
7411                 case Q3TCMOD_ROTATE:
7412                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7413                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7414                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7415                         break;
7416                 case Q3TCMOD_SCALE:
7417                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7418                         break;
7419                 case Q3TCMOD_SCROLL:
7420                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7421                         break;
7422                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7423                         w = (int) tcmod->parms[0];
7424                         h = (int) tcmod->parms[1];
7425                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7426                         f = f - floor(f);
7427                         idx = (int) floor(f * w * h);
7428                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7429                         break;
7430                 case Q3TCMOD_STRETCH:
7431                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7432                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7433                         break;
7434                 case Q3TCMOD_TRANSFORM:
7435                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7436                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7437                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7438                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7439                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7440                         break;
7441                 case Q3TCMOD_TURBULENT:
7442                         // this is handled in the RSurf_PrepareVertices function
7443                         matrix = identitymatrix;
7444                         break;
7445         }
7446         temp = *texmatrix;
7447         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7448 }
7449
7450 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7451 {
7452         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7453         char name[MAX_QPATH];
7454         skinframe_t *skinframe;
7455         unsigned char pixels[296*194];
7456         strlcpy(cache->name, skinname, sizeof(cache->name));
7457         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7458         if (developer_loading.integer)
7459                 Con_Printf("loading %s\n", name);
7460         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7461         if (!skinframe || !skinframe->base)
7462         {
7463                 unsigned char *f;
7464                 fs_offset_t filesize;
7465                 skinframe = NULL;
7466                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7467                 if (f)
7468                 {
7469                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7470                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7471                         Mem_Free(f);
7472                 }
7473         }
7474         cache->skinframe = skinframe;
7475 }
7476
7477 texture_t *R_GetCurrentTexture(texture_t *t)
7478 {
7479         int i;
7480         const entity_render_t *ent = rsurface.entity;
7481         dp_model_t *model = ent->model;
7482         q3shaderinfo_layer_tcmod_t *tcmod;
7483
7484         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7485                 return t->currentframe;
7486         t->update_lastrenderframe = r_textureframe;
7487         t->update_lastrenderentity = (void *)ent;
7488
7489         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7490                 t->camera_entity = ent->entitynumber;
7491         else
7492                 t->camera_entity = 0;
7493
7494         // switch to an alternate material if this is a q1bsp animated material
7495         {
7496                 texture_t *texture = t;
7497                 int s = rsurface.ent_skinnum;
7498                 if ((unsigned int)s >= (unsigned int)model->numskins)
7499                         s = 0;
7500                 if (model->skinscenes)
7501                 {
7502                         if (model->skinscenes[s].framecount > 1)
7503                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7504                         else
7505                                 s = model->skinscenes[s].firstframe;
7506                 }
7507                 if (s > 0)
7508                         t = t + s * model->num_surfaces;
7509                 if (t->animated)
7510                 {
7511                         // use an alternate animation if the entity's frame is not 0,
7512                         // and only if the texture has an alternate animation
7513                         if (rsurface.ent_alttextures && t->anim_total[1])
7514                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7515                         else
7516                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7517                 }
7518                 texture->currentframe = t;
7519         }
7520
7521         // update currentskinframe to be a qw skin or animation frame
7522         if (rsurface.ent_qwskin >= 0)
7523         {
7524                 i = rsurface.ent_qwskin;
7525                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7526                 {
7527                         r_qwskincache_size = cl.maxclients;
7528                         if (r_qwskincache)
7529                                 Mem_Free(r_qwskincache);
7530                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7531                 }
7532                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7533                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7534                 t->currentskinframe = r_qwskincache[i].skinframe;
7535                 if (t->currentskinframe == NULL)
7536                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7537         }
7538         else if (t->numskinframes >= 2)
7539                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7540         if (t->backgroundnumskinframes >= 2)
7541                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7542
7543         t->currentmaterialflags = t->basematerialflags;
7544         t->currentalpha = rsurface.colormod[3];
7545         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7546                 t->currentalpha *= r_wateralpha.value;
7547         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7548                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7549         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7550                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7551         if (!(rsurface.ent_flags & RENDER_LIGHT))
7552                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7553         else if (FAKELIGHT_ENABLED)
7554         {
7555                 // no modellight if using fakelight for the map
7556         }
7557         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7558         {
7559                 // pick a model lighting mode
7560                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7561                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7562                 else
7563                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7564         }
7565         if (rsurface.ent_flags & RENDER_ADDITIVE)
7566                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7567         else if (t->currentalpha < 1)
7568                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7569         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7570                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7571         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7572                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7573         if (t->backgroundnumskinframes)
7574                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7575         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7576         {
7577                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7578                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7579         }
7580         else
7581                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7582         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7583                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7584
7585         // there is no tcmod
7586         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7587         {
7588                 t->currenttexmatrix = r_waterscrollmatrix;
7589                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7590         }
7591         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7592         {
7593                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7594                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7595         }
7596
7597         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7598                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7599         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7600                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7601
7602         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7603         if (t->currentskinframe->qpixels)
7604                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7605         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7606         if (!t->basetexture)
7607                 t->basetexture = r_texture_notexture;
7608         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7609         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7610         t->nmaptexture = t->currentskinframe->nmap;
7611         if (!t->nmaptexture)
7612                 t->nmaptexture = r_texture_blanknormalmap;
7613         t->glosstexture = r_texture_black;
7614         t->glowtexture = t->currentskinframe->glow;
7615         t->fogtexture = t->currentskinframe->fog;
7616         t->reflectmasktexture = t->currentskinframe->reflect;
7617         if (t->backgroundnumskinframes)
7618         {
7619                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7620                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7621                 t->backgroundglosstexture = r_texture_black;
7622                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7623                 if (!t->backgroundnmaptexture)
7624                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7625         }
7626         else
7627         {
7628                 t->backgroundbasetexture = r_texture_white;
7629                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7630                 t->backgroundglosstexture = r_texture_black;
7631                 t->backgroundglowtexture = NULL;
7632         }
7633         t->specularpower = r_shadow_glossexponent.value;
7634         // TODO: store reference values for these in the texture?
7635         t->specularscale = 0;
7636         if (r_shadow_gloss.integer > 0)
7637         {
7638                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7639                 {
7640                         if (r_shadow_glossintensity.value > 0)
7641                         {
7642                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7643                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7644                                 t->specularscale = r_shadow_glossintensity.value;
7645                         }
7646                 }
7647                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7648                 {
7649                         t->glosstexture = r_texture_white;
7650                         t->backgroundglosstexture = r_texture_white;
7651                         t->specularscale = r_shadow_gloss2intensity.value;
7652                         t->specularpower = r_shadow_gloss2exponent.value;
7653                 }
7654         }
7655         t->specularscale *= t->specularscalemod;
7656         t->specularpower *= t->specularpowermod;
7657
7658         // lightmaps mode looks bad with dlights using actual texturing, so turn
7659         // off the colormap and glossmap, but leave the normalmap on as it still
7660         // accurately represents the shading involved
7661         if (gl_lightmaps.integer)
7662         {
7663                 t->basetexture = r_texture_grey128;
7664                 t->pantstexture = r_texture_black;
7665                 t->shirttexture = r_texture_black;
7666                 t->nmaptexture = r_texture_blanknormalmap;
7667                 t->glosstexture = r_texture_black;
7668                 t->glowtexture = NULL;
7669                 t->fogtexture = NULL;
7670                 t->reflectmasktexture = NULL;
7671                 t->backgroundbasetexture = NULL;
7672                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7673                 t->backgroundglosstexture = r_texture_black;
7674                 t->backgroundglowtexture = NULL;
7675                 t->specularscale = 0;
7676                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7677         }
7678
7679         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7680         VectorClear(t->dlightcolor);
7681         t->currentnumlayers = 0;
7682         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7683         {
7684                 int blendfunc1, blendfunc2;
7685                 qboolean depthmask;
7686                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7687                 {
7688                         blendfunc1 = GL_SRC_ALPHA;
7689                         blendfunc2 = GL_ONE;
7690                 }
7691                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7692                 {
7693                         blendfunc1 = GL_SRC_ALPHA;
7694                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7695                 }
7696                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7697                 {
7698                         blendfunc1 = t->customblendfunc[0];
7699                         blendfunc2 = t->customblendfunc[1];
7700                 }
7701                 else
7702                 {
7703                         blendfunc1 = GL_ONE;
7704                         blendfunc2 = GL_ZERO;
7705                 }
7706                 // don't colormod evilblend textures
7707                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7708                         VectorSet(t->lightmapcolor, 1, 1, 1);
7709                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7710                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7711                 {
7712                         // fullbright is not affected by r_refdef.lightmapintensity
7713                         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]);
7714                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7715                                 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]);
7716                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7717                                 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]);
7718                 }
7719                 else
7720                 {
7721                         vec3_t ambientcolor;
7722                         float colorscale;
7723                         // set the color tint used for lights affecting this surface
7724                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7725                         colorscale = 2;
7726                         // q3bsp has no lightmap updates, so the lightstylevalue that
7727                         // would normally be baked into the lightmap must be
7728                         // applied to the color
7729                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7730                         if (model->type == mod_brushq3)
7731                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7732                         colorscale *= r_refdef.lightmapintensity;
7733                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7734                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7735                         // basic lit geometry
7736                         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]);
7737                         // add pants/shirt if needed
7738                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7739                                 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]);
7740                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7741                                 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]);
7742                         // now add ambient passes if needed
7743                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7744                         {
7745                                 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]);
7746                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7747                                         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]);
7748                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7749                                         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]);
7750                         }
7751                 }
7752                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7753                         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]);
7754                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7755                 {
7756                         // if this is opaque use alpha blend which will darken the earlier
7757                         // passes cheaply.
7758                         //
7759                         // if this is an alpha blended material, all the earlier passes
7760                         // were darkened by fog already, so we only need to add the fog
7761                         // color ontop through the fog mask texture
7762                         //
7763                         // if this is an additive blended material, all the earlier passes
7764                         // were darkened by fog already, and we should not add fog color
7765                         // (because the background was not darkened, there is no fog color
7766                         // that was lost behind it).
7767                         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]);
7768                 }
7769         }
7770
7771         return t->currentframe;
7772 }
7773
7774 rsurfacestate_t rsurface;
7775
7776 void RSurf_ActiveWorldEntity(void)
7777 {
7778         dp_model_t *model = r_refdef.scene.worldmodel;
7779         //if (rsurface.entity == r_refdef.scene.worldentity)
7780         //      return;
7781         rsurface.entity = r_refdef.scene.worldentity;
7782         rsurface.skeleton = NULL;
7783         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7784         rsurface.ent_skinnum = 0;
7785         rsurface.ent_qwskin = -1;
7786         rsurface.ent_shadertime = 0;
7787         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7788         rsurface.matrix = identitymatrix;
7789         rsurface.inversematrix = identitymatrix;
7790         rsurface.matrixscale = 1;
7791         rsurface.inversematrixscale = 1;
7792         R_EntityMatrix(&identitymatrix);
7793         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7794         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7795         rsurface.fograngerecip = r_refdef.fograngerecip;
7796         rsurface.fogheightfade = r_refdef.fogheightfade;
7797         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7798         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7799         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7800         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7801         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7802         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7803         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7804         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7805         rsurface.colormod[3] = 1;
7806         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);
7807         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7808         rsurface.frameblend[0].lerp = 1;
7809         rsurface.ent_alttextures = false;
7810         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7811         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7812         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7813         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7814         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7815         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7816         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7817         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7818         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7819         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7820         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7821         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7822         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7823         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7824         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7825         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7826         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7827         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7828         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7829         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7830         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7831         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7832         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7833         rsurface.modelelement3i = model->surfmesh.data_element3i;
7834         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7835         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7836         rsurface.modelelement3s = model->surfmesh.data_element3s;
7837         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7838         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7839         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7840         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7841         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7842         rsurface.modelsurfaces = model->data_surfaces;
7843         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7844         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7845         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7846         rsurface.modelgeneratedvertex = false;
7847         rsurface.batchgeneratedvertex = false;
7848         rsurface.batchfirstvertex = 0;
7849         rsurface.batchnumvertices = 0;
7850         rsurface.batchfirsttriangle = 0;
7851         rsurface.batchnumtriangles = 0;
7852         rsurface.batchvertex3f  = NULL;
7853         rsurface.batchvertex3f_vertexbuffer = NULL;
7854         rsurface.batchvertex3f_bufferoffset = 0;
7855         rsurface.batchsvector3f = NULL;
7856         rsurface.batchsvector3f_vertexbuffer = NULL;
7857         rsurface.batchsvector3f_bufferoffset = 0;
7858         rsurface.batchtvector3f = NULL;
7859         rsurface.batchtvector3f_vertexbuffer = NULL;
7860         rsurface.batchtvector3f_bufferoffset = 0;
7861         rsurface.batchnormal3f  = NULL;
7862         rsurface.batchnormal3f_vertexbuffer = NULL;
7863         rsurface.batchnormal3f_bufferoffset = 0;
7864         rsurface.batchlightmapcolor4f = NULL;
7865         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7866         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7867         rsurface.batchtexcoordtexture2f = NULL;
7868         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7869         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7870         rsurface.batchtexcoordlightmap2f = NULL;
7871         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7872         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7873         rsurface.batchvertexmesh = NULL;
7874         rsurface.batchvertexmeshbuffer = NULL;
7875         rsurface.batchvertex3fbuffer = NULL;
7876         rsurface.batchelement3i = NULL;
7877         rsurface.batchelement3i_indexbuffer = NULL;
7878         rsurface.batchelement3i_bufferoffset = 0;
7879         rsurface.batchelement3s = NULL;
7880         rsurface.batchelement3s_indexbuffer = NULL;
7881         rsurface.batchelement3s_bufferoffset = 0;
7882         rsurface.passcolor4f = NULL;
7883         rsurface.passcolor4f_vertexbuffer = NULL;
7884         rsurface.passcolor4f_bufferoffset = 0;
7885 }
7886
7887 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7888 {
7889         dp_model_t *model = ent->model;
7890         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7891         //      return;
7892         rsurface.entity = (entity_render_t *)ent;
7893         rsurface.skeleton = ent->skeleton;
7894         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7895         rsurface.ent_skinnum = ent->skinnum;
7896         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;
7897         rsurface.ent_shadertime = ent->shadertime;
7898         rsurface.ent_flags = ent->flags;
7899         rsurface.matrix = ent->matrix;
7900         rsurface.inversematrix = ent->inversematrix;
7901         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7902         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7903         R_EntityMatrix(&rsurface.matrix);
7904         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7905         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7906         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7907         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7908         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7909         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7910         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7911         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7912         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7913         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7914         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7915         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7916         rsurface.colormod[3] = ent->alpha;
7917         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7918         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7919         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7920         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7921         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7922         if (ent->model->brush.submodel && !prepass)
7923         {
7924                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7925                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7926         }
7927         if (model->surfmesh.isanimated && model->AnimateVertices)
7928         {
7929                 if (ent->animcache_vertex3f)
7930                 {
7931                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7932                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7933                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7934                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7935                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7936                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7937                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7938                 }
7939                 else if (wanttangents)
7940                 {
7941                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7942                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7943                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7944                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7945                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7946                         rsurface.modelvertexmesh = NULL;
7947                         rsurface.modelvertexmeshbuffer = NULL;
7948                         rsurface.modelvertex3fbuffer = NULL;
7949                 }
7950                 else if (wantnormals)
7951                 {
7952                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7953                         rsurface.modelsvector3f = NULL;
7954                         rsurface.modeltvector3f = NULL;
7955                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7956                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7957                         rsurface.modelvertexmesh = NULL;
7958                         rsurface.modelvertexmeshbuffer = NULL;
7959                         rsurface.modelvertex3fbuffer = NULL;
7960                 }
7961                 else
7962                 {
7963                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7964                         rsurface.modelsvector3f = NULL;
7965                         rsurface.modeltvector3f = NULL;
7966                         rsurface.modelnormal3f = NULL;
7967                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7968                         rsurface.modelvertexmesh = NULL;
7969                         rsurface.modelvertexmeshbuffer = NULL;
7970                         rsurface.modelvertex3fbuffer = NULL;
7971                 }
7972                 rsurface.modelvertex3f_vertexbuffer = 0;
7973                 rsurface.modelvertex3f_bufferoffset = 0;
7974                 rsurface.modelsvector3f_vertexbuffer = 0;
7975                 rsurface.modelsvector3f_bufferoffset = 0;
7976                 rsurface.modeltvector3f_vertexbuffer = 0;
7977                 rsurface.modeltvector3f_bufferoffset = 0;
7978                 rsurface.modelnormal3f_vertexbuffer = 0;
7979                 rsurface.modelnormal3f_bufferoffset = 0;
7980                 rsurface.modelgeneratedvertex = true;
7981         }
7982         else
7983         {
7984                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7985                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7986                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7987                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7988                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7989                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7990                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7991                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7992                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7993                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7994                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7995                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7996                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7997                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7998                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7999                 rsurface.modelgeneratedvertex = false;
8000         }
8001         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8002         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8003         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8004         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8005         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8006         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8007         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8008         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8009         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8010         rsurface.modelelement3i = model->surfmesh.data_element3i;
8011         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8012         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8013         rsurface.modelelement3s = model->surfmesh.data_element3s;
8014         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8015         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8016         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8017         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8018         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8019         rsurface.modelsurfaces = model->data_surfaces;
8020         rsurface.batchgeneratedvertex = false;
8021         rsurface.batchfirstvertex = 0;
8022         rsurface.batchnumvertices = 0;
8023         rsurface.batchfirsttriangle = 0;
8024         rsurface.batchnumtriangles = 0;
8025         rsurface.batchvertex3f  = NULL;
8026         rsurface.batchvertex3f_vertexbuffer = NULL;
8027         rsurface.batchvertex3f_bufferoffset = 0;
8028         rsurface.batchsvector3f = NULL;
8029         rsurface.batchsvector3f_vertexbuffer = NULL;
8030         rsurface.batchsvector3f_bufferoffset = 0;
8031         rsurface.batchtvector3f = NULL;
8032         rsurface.batchtvector3f_vertexbuffer = NULL;
8033         rsurface.batchtvector3f_bufferoffset = 0;
8034         rsurface.batchnormal3f  = NULL;
8035         rsurface.batchnormal3f_vertexbuffer = NULL;
8036         rsurface.batchnormal3f_bufferoffset = 0;
8037         rsurface.batchlightmapcolor4f = NULL;
8038         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8039         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8040         rsurface.batchtexcoordtexture2f = NULL;
8041         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8042         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8043         rsurface.batchtexcoordlightmap2f = NULL;
8044         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8045         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8046         rsurface.batchvertexmesh = NULL;
8047         rsurface.batchvertexmeshbuffer = NULL;
8048         rsurface.batchvertex3fbuffer = NULL;
8049         rsurface.batchelement3i = NULL;
8050         rsurface.batchelement3i_indexbuffer = NULL;
8051         rsurface.batchelement3i_bufferoffset = 0;
8052         rsurface.batchelement3s = NULL;
8053         rsurface.batchelement3s_indexbuffer = NULL;
8054         rsurface.batchelement3s_bufferoffset = 0;
8055         rsurface.passcolor4f = NULL;
8056         rsurface.passcolor4f_vertexbuffer = NULL;
8057         rsurface.passcolor4f_bufferoffset = 0;
8058 }
8059
8060 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)
8061 {
8062         rsurface.entity = r_refdef.scene.worldentity;
8063         rsurface.skeleton = NULL;
8064         rsurface.ent_skinnum = 0;
8065         rsurface.ent_qwskin = -1;
8066         rsurface.ent_shadertime = shadertime;
8067         rsurface.ent_flags = entflags;
8068         rsurface.modelnumvertices = numvertices;
8069         rsurface.modelnumtriangles = numtriangles;
8070         rsurface.matrix = *matrix;
8071         rsurface.inversematrix = *inversematrix;
8072         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8073         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8074         R_EntityMatrix(&rsurface.matrix);
8075         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8076         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8077         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8078         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8079         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8080         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8081         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8082         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8083         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8084         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8085         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8086         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8087         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);
8088         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8089         rsurface.frameblend[0].lerp = 1;
8090         rsurface.ent_alttextures = false;
8091         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8092         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8093         if (wanttangents)
8094         {
8095                 rsurface.modelvertex3f = (float *)vertex3f;
8096                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8097                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8098                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8099         }
8100         else if (wantnormals)
8101         {
8102                 rsurface.modelvertex3f = (float *)vertex3f;
8103                 rsurface.modelsvector3f = NULL;
8104                 rsurface.modeltvector3f = NULL;
8105                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8106         }
8107         else
8108         {
8109                 rsurface.modelvertex3f = (float *)vertex3f;
8110                 rsurface.modelsvector3f = NULL;
8111                 rsurface.modeltvector3f = NULL;
8112                 rsurface.modelnormal3f = NULL;
8113         }
8114         rsurface.modelvertexmesh = NULL;
8115         rsurface.modelvertexmeshbuffer = NULL;
8116         rsurface.modelvertex3fbuffer = NULL;
8117         rsurface.modelvertex3f_vertexbuffer = 0;
8118         rsurface.modelvertex3f_bufferoffset = 0;
8119         rsurface.modelsvector3f_vertexbuffer = 0;
8120         rsurface.modelsvector3f_bufferoffset = 0;
8121         rsurface.modeltvector3f_vertexbuffer = 0;
8122         rsurface.modeltvector3f_bufferoffset = 0;
8123         rsurface.modelnormal3f_vertexbuffer = 0;
8124         rsurface.modelnormal3f_bufferoffset = 0;
8125         rsurface.modelgeneratedvertex = true;
8126         rsurface.modellightmapcolor4f  = (float *)color4f;
8127         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8128         rsurface.modellightmapcolor4f_bufferoffset = 0;
8129         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8130         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8131         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8132         rsurface.modeltexcoordlightmap2f  = NULL;
8133         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8134         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8135         rsurface.modelelement3i = (int *)element3i;
8136         rsurface.modelelement3i_indexbuffer = NULL;
8137         rsurface.modelelement3i_bufferoffset = 0;
8138         rsurface.modelelement3s = (unsigned short *)element3s;
8139         rsurface.modelelement3s_indexbuffer = NULL;
8140         rsurface.modelelement3s_bufferoffset = 0;
8141         rsurface.modellightmapoffsets = NULL;
8142         rsurface.modelsurfaces = NULL;
8143         rsurface.batchgeneratedvertex = false;
8144         rsurface.batchfirstvertex = 0;
8145         rsurface.batchnumvertices = 0;
8146         rsurface.batchfirsttriangle = 0;
8147         rsurface.batchnumtriangles = 0;
8148         rsurface.batchvertex3f  = NULL;
8149         rsurface.batchvertex3f_vertexbuffer = NULL;
8150         rsurface.batchvertex3f_bufferoffset = 0;
8151         rsurface.batchsvector3f = NULL;
8152         rsurface.batchsvector3f_vertexbuffer = NULL;
8153         rsurface.batchsvector3f_bufferoffset = 0;
8154         rsurface.batchtvector3f = NULL;
8155         rsurface.batchtvector3f_vertexbuffer = NULL;
8156         rsurface.batchtvector3f_bufferoffset = 0;
8157         rsurface.batchnormal3f  = NULL;
8158         rsurface.batchnormal3f_vertexbuffer = NULL;
8159         rsurface.batchnormal3f_bufferoffset = 0;
8160         rsurface.batchlightmapcolor4f = NULL;
8161         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8162         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8163         rsurface.batchtexcoordtexture2f = NULL;
8164         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8165         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8166         rsurface.batchtexcoordlightmap2f = NULL;
8167         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8168         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8169         rsurface.batchvertexmesh = NULL;
8170         rsurface.batchvertexmeshbuffer = NULL;
8171         rsurface.batchvertex3fbuffer = NULL;
8172         rsurface.batchelement3i = NULL;
8173         rsurface.batchelement3i_indexbuffer = NULL;
8174         rsurface.batchelement3i_bufferoffset = 0;
8175         rsurface.batchelement3s = NULL;
8176         rsurface.batchelement3s_indexbuffer = NULL;
8177         rsurface.batchelement3s_bufferoffset = 0;
8178         rsurface.passcolor4f = NULL;
8179         rsurface.passcolor4f_vertexbuffer = NULL;
8180         rsurface.passcolor4f_bufferoffset = 0;
8181
8182         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8183         {
8184                 if ((wantnormals || wanttangents) && !normal3f)
8185                 {
8186                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8187                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8188                 }
8189                 if (wanttangents && !svector3f)
8190                 {
8191                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8192                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8193                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8194                 }
8195         }
8196 }
8197
8198 float RSurf_FogPoint(const float *v)
8199 {
8200         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8201         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8202         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8203         float FogHeightFade = r_refdef.fogheightfade;
8204         float fogfrac;
8205         unsigned int fogmasktableindex;
8206         if (r_refdef.fogplaneviewabove)
8207                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8208         else
8209                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8210         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8211         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8212 }
8213
8214 float RSurf_FogVertex(const float *v)
8215 {
8216         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8217         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8218         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8219         float FogHeightFade = rsurface.fogheightfade;
8220         float fogfrac;
8221         unsigned int fogmasktableindex;
8222         if (r_refdef.fogplaneviewabove)
8223                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8224         else
8225                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8226         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8227         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8228 }
8229
8230 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8231 {
8232         int i;
8233         for (i = 0;i < numelements;i++)
8234                 outelement3i[i] = inelement3i[i] + adjust;
8235 }
8236
8237 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8238 extern cvar_t gl_vbo;
8239 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8240 {
8241         int deformindex;
8242         int firsttriangle;
8243         int numtriangles;
8244         int firstvertex;
8245         int endvertex;
8246         int numvertices;
8247         int surfacefirsttriangle;
8248         int surfacenumtriangles;
8249         int surfacefirstvertex;
8250         int surfaceendvertex;
8251         int surfacenumvertices;
8252         int batchnumvertices;
8253         int batchnumtriangles;
8254         int needsupdate;
8255         int i, j;
8256         qboolean gaps;
8257         qboolean dynamicvertex;
8258         float amplitude;
8259         float animpos;
8260         float scale;
8261         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8262         float waveparms[4];
8263         q3shaderinfo_deform_t *deform;
8264         const msurface_t *surface, *firstsurface;
8265         r_vertexmesh_t *vertexmesh;
8266         if (!texturenumsurfaces)
8267                 return;
8268         // find vertex range of this surface batch
8269         gaps = false;
8270         firstsurface = texturesurfacelist[0];
8271         firsttriangle = firstsurface->num_firsttriangle;
8272         batchnumvertices = 0;
8273         batchnumtriangles = 0;
8274         firstvertex = endvertex = firstsurface->num_firstvertex;
8275         for (i = 0;i < texturenumsurfaces;i++)
8276         {
8277                 surface = texturesurfacelist[i];
8278                 if (surface != firstsurface + i)
8279                         gaps = true;
8280                 surfacefirstvertex = surface->num_firstvertex;
8281                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8282                 surfacenumvertices = surface->num_vertices;
8283                 surfacenumtriangles = surface->num_triangles;
8284                 if (firstvertex > surfacefirstvertex)
8285                         firstvertex = surfacefirstvertex;
8286                 if (endvertex < surfaceendvertex)
8287                         endvertex = surfaceendvertex;
8288                 batchnumvertices += surfacenumvertices;
8289                 batchnumtriangles += surfacenumtriangles;
8290         }
8291
8292         // we now know the vertex range used, and if there are any gaps in it
8293         rsurface.batchfirstvertex = firstvertex;
8294         rsurface.batchnumvertices = endvertex - firstvertex;
8295         rsurface.batchfirsttriangle = firsttriangle;
8296         rsurface.batchnumtriangles = batchnumtriangles;
8297
8298         // this variable holds flags for which properties have been updated that
8299         // may require regenerating vertexmesh array...
8300         needsupdate = 0;
8301
8302         // check if any dynamic vertex processing must occur
8303         dynamicvertex = false;
8304
8305         // if there is a chance of animated vertex colors, it's a dynamic batch
8306         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8307         {
8308                 dynamicvertex = true;
8309                 batchneed |= BATCHNEED_NOGAPS;
8310                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8311         }
8312
8313         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8314         {
8315                 switch (deform->deform)
8316                 {
8317                 default:
8318                 case Q3DEFORM_PROJECTIONSHADOW:
8319                 case Q3DEFORM_TEXT0:
8320                 case Q3DEFORM_TEXT1:
8321                 case Q3DEFORM_TEXT2:
8322                 case Q3DEFORM_TEXT3:
8323                 case Q3DEFORM_TEXT4:
8324                 case Q3DEFORM_TEXT5:
8325                 case Q3DEFORM_TEXT6:
8326                 case Q3DEFORM_TEXT7:
8327                 case Q3DEFORM_NONE:
8328                         break;
8329                 case Q3DEFORM_AUTOSPRITE:
8330                         dynamicvertex = true;
8331                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8332                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8333                         break;
8334                 case Q3DEFORM_AUTOSPRITE2:
8335                         dynamicvertex = true;
8336                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8337                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8338                         break;
8339                 case Q3DEFORM_NORMAL:
8340                         dynamicvertex = true;
8341                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8342                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8343                         break;
8344                 case Q3DEFORM_WAVE:
8345                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8346                                 break; // if wavefunc is a nop, ignore this transform
8347                         dynamicvertex = true;
8348                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8349                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8350                         break;
8351                 case Q3DEFORM_BULGE:
8352                         dynamicvertex = true;
8353                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8354                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8355                         break;
8356                 case Q3DEFORM_MOVE:
8357                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8358                                 break; // if wavefunc is a nop, ignore this transform
8359                         dynamicvertex = true;
8360                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8361                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8362                         break;
8363                 }
8364         }
8365         switch(rsurface.texture->tcgen.tcgen)
8366         {
8367         default:
8368         case Q3TCGEN_TEXTURE:
8369                 break;
8370         case Q3TCGEN_LIGHTMAP:
8371                 dynamicvertex = true;
8372                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8373                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8374                 break;
8375         case Q3TCGEN_VECTOR:
8376                 dynamicvertex = true;
8377                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8378                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8379                 break;
8380         case Q3TCGEN_ENVIRONMENT:
8381                 dynamicvertex = true;
8382                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8383                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8384                 break;
8385         }
8386         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8387         {
8388                 dynamicvertex = true;
8389                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8390                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8391         }
8392
8393         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8394         {
8395                 dynamicvertex = true;
8396                 batchneed |= BATCHNEED_NOGAPS;
8397                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8398         }
8399
8400         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8401         {
8402                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8403                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8404                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8405                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8406                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8407                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8408                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8409         }
8410
8411         // when the model data has no vertex buffer (dynamic mesh), we need to
8412         // eliminate gaps
8413         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8414                 batchneed |= BATCHNEED_NOGAPS;
8415
8416         // if needsupdate, we have to do a dynamic vertex batch for sure
8417         if (needsupdate & batchneed)
8418                 dynamicvertex = true;
8419
8420         // see if we need to build vertexmesh from arrays
8421         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8422                 dynamicvertex = true;
8423
8424         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8425         // also some drivers strongly dislike firstvertex
8426         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8427                 dynamicvertex = true;
8428
8429         rsurface.batchvertex3f = rsurface.modelvertex3f;
8430         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8431         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8432         rsurface.batchsvector3f = rsurface.modelsvector3f;
8433         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8434         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8435         rsurface.batchtvector3f = rsurface.modeltvector3f;
8436         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8437         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8438         rsurface.batchnormal3f = rsurface.modelnormal3f;
8439         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8440         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8441         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8442         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8443         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8444         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8445         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8446         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8447         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8448         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8449         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8450         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8451         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8452         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8453         rsurface.batchelement3i = rsurface.modelelement3i;
8454         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8455         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8456         rsurface.batchelement3s = rsurface.modelelement3s;
8457         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8458         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8459
8460         // if any dynamic vertex processing has to occur in software, we copy the
8461         // entire surface list together before processing to rebase the vertices
8462         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8463         //
8464         // if any gaps exist and we do not have a static vertex buffer, we have to
8465         // copy the surface list together to avoid wasting upload bandwidth on the
8466         // vertices in the gaps.
8467         //
8468         // if gaps exist and we have a static vertex buffer, we still have to
8469         // combine the index buffer ranges into one dynamic index buffer.
8470         //
8471         // in all cases we end up with data that can be drawn in one call.
8472
8473         if (!dynamicvertex)
8474         {
8475                 // static vertex data, just set pointers...
8476                 rsurface.batchgeneratedvertex = false;
8477                 // if there are gaps, we want to build a combined index buffer,
8478                 // otherwise use the original static buffer with an appropriate offset
8479                 if (gaps)
8480                 {
8481                         // build a new triangle elements array for this batch
8482                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8483                         rsurface.batchfirsttriangle = 0;
8484                         numtriangles = 0;
8485                         for (i = 0;i < texturenumsurfaces;i++)
8486                         {
8487                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8488                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8489                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8490                                 numtriangles += surfacenumtriangles;
8491                         }
8492                         rsurface.batchelement3i_indexbuffer = NULL;
8493                         rsurface.batchelement3i_bufferoffset = 0;
8494                         rsurface.batchelement3s = NULL;
8495                         rsurface.batchelement3s_indexbuffer = NULL;
8496                         rsurface.batchelement3s_bufferoffset = 0;
8497                         if (endvertex <= 65536)
8498                         {
8499                                 // make a 16bit (unsigned short) index array if possible
8500                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8501                                 for (i = 0;i < numtriangles*3;i++)
8502                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8503                         }
8504                 }
8505                 return;
8506         }
8507
8508         // something needs software processing, do it for real...
8509         // we only directly handle separate array data in this case and then
8510         // generate interleaved data if needed...
8511         rsurface.batchgeneratedvertex = true;
8512
8513         // now copy the vertex data into a combined array and make an index array
8514         // (this is what Quake3 does all the time)
8515         //if (gaps || rsurface.batchfirstvertex)
8516         {
8517                 rsurface.batchvertex3fbuffer = NULL;
8518                 rsurface.batchvertexmesh = NULL;
8519                 rsurface.batchvertexmeshbuffer = NULL;
8520                 rsurface.batchvertex3f = NULL;
8521                 rsurface.batchvertex3f_vertexbuffer = NULL;
8522                 rsurface.batchvertex3f_bufferoffset = 0;
8523                 rsurface.batchsvector3f = NULL;
8524                 rsurface.batchsvector3f_vertexbuffer = NULL;
8525                 rsurface.batchsvector3f_bufferoffset = 0;
8526                 rsurface.batchtvector3f = NULL;
8527                 rsurface.batchtvector3f_vertexbuffer = NULL;
8528                 rsurface.batchtvector3f_bufferoffset = 0;
8529                 rsurface.batchnormal3f = NULL;
8530                 rsurface.batchnormal3f_vertexbuffer = NULL;
8531                 rsurface.batchnormal3f_bufferoffset = 0;
8532                 rsurface.batchlightmapcolor4f = NULL;
8533                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8534                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8535                 rsurface.batchtexcoordtexture2f = NULL;
8536                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8537                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8538                 rsurface.batchtexcoordlightmap2f = NULL;
8539                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8540                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8541                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8542                 rsurface.batchelement3i_indexbuffer = NULL;
8543                 rsurface.batchelement3i_bufferoffset = 0;
8544                 rsurface.batchelement3s = NULL;
8545                 rsurface.batchelement3s_indexbuffer = NULL;
8546                 rsurface.batchelement3s_bufferoffset = 0;
8547                 // we'll only be setting up certain arrays as needed
8548                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8549                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8550                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8551                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8552                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8553                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8554                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8555                 {
8556                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8557                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8558                 }
8559                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8560                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8561                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8562                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8563                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8564                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8565                 numvertices = 0;
8566                 numtriangles = 0;
8567                 for (i = 0;i < texturenumsurfaces;i++)
8568                 {
8569                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8570                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8571                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8572                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8573                         // copy only the data requested
8574                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8575                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8576                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8577                         {
8578                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8579                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8580                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8581                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8582                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8583                                 {
8584                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8585                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8586                                 }
8587                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8588                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8589                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8590                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8591                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8592                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8593                         }
8594                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8595                         numvertices += surfacenumvertices;
8596                         numtriangles += surfacenumtriangles;
8597                 }
8598
8599                 // generate a 16bit index array as well if possible
8600                 // (in general, dynamic batches fit)
8601                 if (numvertices <= 65536)
8602                 {
8603                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8604                         for (i = 0;i < numtriangles*3;i++)
8605                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8606                 }
8607
8608                 // since we've copied everything, the batch now starts at 0
8609                 rsurface.batchfirstvertex = 0;
8610                 rsurface.batchnumvertices = batchnumvertices;
8611                 rsurface.batchfirsttriangle = 0;
8612                 rsurface.batchnumtriangles = batchnumtriangles;
8613         }
8614
8615         // q1bsp surfaces rendered in vertex color mode have to have colors
8616         // calculated based on lightstyles
8617         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8618         {
8619                 // generate color arrays for the surfaces in this list
8620                 int c[4];
8621                 int scale;
8622                 int size3;
8623                 const int *offsets;
8624                 const unsigned char *lm;
8625                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8626                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8627                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8628                 numvertices = 0;
8629                 for (i = 0;i < texturenumsurfaces;i++)
8630                 {
8631                         surface = texturesurfacelist[i];
8632                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8633                         surfacenumvertices = surface->num_vertices;
8634                         if (surface->lightmapinfo->samples)
8635                         {
8636                                 for (j = 0;j < surfacenumvertices;j++)
8637                                 {
8638                                         lm = surface->lightmapinfo->samples + offsets[j];
8639                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8640                                         VectorScale(lm, scale, c);
8641                                         if (surface->lightmapinfo->styles[1] != 255)
8642                                         {
8643                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8644                                                 lm += size3;
8645                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8646                                                 VectorMA(c, scale, lm, c);
8647                                                 if (surface->lightmapinfo->styles[2] != 255)
8648                                                 {
8649                                                         lm += size3;
8650                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8651                                                         VectorMA(c, scale, lm, c);
8652                                                         if (surface->lightmapinfo->styles[3] != 255)
8653                                                         {
8654                                                                 lm += size3;
8655                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8656                                                                 VectorMA(c, scale, lm, c);
8657                                                         }
8658                                                 }
8659                                         }
8660                                         c[0] >>= 7;
8661                                         c[1] >>= 7;
8662                                         c[2] >>= 7;
8663                                         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);
8664                                         numvertices++;
8665                                 }
8666                         }
8667                         else
8668                         {
8669                                 for (j = 0;j < surfacenumvertices;j++)
8670                                 {
8671                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8672                                         numvertices++;
8673                                 }
8674                         }
8675                 }
8676         }
8677
8678         // if vertices are deformed (sprite flares and things in maps, possibly
8679         // water waves, bulges and other deformations), modify the copied vertices
8680         // in place
8681         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8682         {
8683                 switch (deform->deform)
8684                 {
8685                 default:
8686                 case Q3DEFORM_PROJECTIONSHADOW:
8687                 case Q3DEFORM_TEXT0:
8688                 case Q3DEFORM_TEXT1:
8689                 case Q3DEFORM_TEXT2:
8690                 case Q3DEFORM_TEXT3:
8691                 case Q3DEFORM_TEXT4:
8692                 case Q3DEFORM_TEXT5:
8693                 case Q3DEFORM_TEXT6:
8694                 case Q3DEFORM_TEXT7:
8695                 case Q3DEFORM_NONE:
8696                         break;
8697                 case Q3DEFORM_AUTOSPRITE:
8698                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8699                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8700                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8701                         VectorNormalize(newforward);
8702                         VectorNormalize(newright);
8703                         VectorNormalize(newup);
8704 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8705 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8706 //                      rsurface.batchvertex3f_bufferoffset = 0;
8707 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8708 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8709 //                      rsurface.batchsvector3f_bufferoffset = 0;
8710 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8711 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8712 //                      rsurface.batchtvector3f_bufferoffset = 0;
8713 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8714 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8715 //                      rsurface.batchnormal3f_bufferoffset = 0;
8716                         // a single autosprite surface can contain multiple sprites...
8717                         for (j = 0;j < batchnumvertices - 3;j += 4)
8718                         {
8719                                 VectorClear(center);
8720                                 for (i = 0;i < 4;i++)
8721                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8722                                 VectorScale(center, 0.25f, center);
8723                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8724                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8725                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8726                                 for (i = 0;i < 4;i++)
8727                                 {
8728                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8729                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8730                                 }
8731                         }
8732                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8733                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8734                         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);
8735                         break;
8736                 case Q3DEFORM_AUTOSPRITE2:
8737                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8738                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8739                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8740                         VectorNormalize(newforward);
8741                         VectorNormalize(newright);
8742                         VectorNormalize(newup);
8743 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8744 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8745 //                      rsurface.batchvertex3f_bufferoffset = 0;
8746                         {
8747                                 const float *v1, *v2;
8748                                 vec3_t start, end;
8749                                 float f, l;
8750                                 struct
8751                                 {
8752                                         float length2;
8753                                         const float *v1;
8754                                         const float *v2;
8755                                 }
8756                                 shortest[2];
8757                                 memset(shortest, 0, sizeof(shortest));
8758                                 // a single autosprite surface can contain multiple sprites...
8759                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8760                                 {
8761                                         VectorClear(center);
8762                                         for (i = 0;i < 4;i++)
8763                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8764                                         VectorScale(center, 0.25f, center);
8765                                         // find the two shortest edges, then use them to define the
8766                                         // axis vectors for rotating around the central axis
8767                                         for (i = 0;i < 6;i++)
8768                                         {
8769                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8770                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8771                                                 l = VectorDistance2(v1, v2);
8772                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8773                                                 if (v1[2] != v2[2])
8774                                                         l += (1.0f / 1024.0f);
8775                                                 if (shortest[0].length2 > l || i == 0)
8776                                                 {
8777                                                         shortest[1] = shortest[0];
8778                                                         shortest[0].length2 = l;
8779                                                         shortest[0].v1 = v1;
8780                                                         shortest[0].v2 = v2;
8781                                                 }
8782                                                 else if (shortest[1].length2 > l || i == 1)
8783                                                 {
8784                                                         shortest[1].length2 = l;
8785                                                         shortest[1].v1 = v1;
8786                                                         shortest[1].v2 = v2;
8787                                                 }
8788                                         }
8789                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8790                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8791                                         // this calculates the right vector from the shortest edge
8792                                         // and the up vector from the edge midpoints
8793                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8794                                         VectorNormalize(right);
8795                                         VectorSubtract(end, start, up);
8796                                         VectorNormalize(up);
8797                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8798                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8799                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8800                                         VectorNegate(forward, forward);
8801                                         VectorReflect(forward, 0, up, forward);
8802                                         VectorNormalize(forward);
8803                                         CrossProduct(up, forward, newright);
8804                                         VectorNormalize(newright);
8805                                         // rotate the quad around the up axis vector, this is made
8806                                         // especially easy by the fact we know the quad is flat,
8807                                         // so we only have to subtract the center position and
8808                                         // measure distance along the right vector, and then
8809                                         // multiply that by the newright vector and add back the
8810                                         // center position
8811                                         // we also need to subtract the old position to undo the
8812                                         // displacement from the center, which we do with a
8813                                         // DotProduct, the subtraction/addition of center is also
8814                                         // optimized into DotProducts here
8815                                         l = DotProduct(right, center);
8816                                         for (i = 0;i < 4;i++)
8817                                         {
8818                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8819                                                 f = DotProduct(right, v1) - l;
8820                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8821                                         }
8822                                 }
8823                         }
8824                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8825                         {
8826 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8828 //                              rsurface.batchnormal3f_bufferoffset = 0;
8829                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8830                         }
8831                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8832                         {
8833 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8835 //                              rsurface.batchsvector3f_bufferoffset = 0;
8836 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8837 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8838 //                              rsurface.batchtvector3f_bufferoffset = 0;
8839                                 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);
8840                         }
8841                         break;
8842                 case Q3DEFORM_NORMAL:
8843                         // deform the normals to make reflections wavey
8844                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8845                         rsurface.batchnormal3f_vertexbuffer = NULL;
8846                         rsurface.batchnormal3f_bufferoffset = 0;
8847                         for (j = 0;j < batchnumvertices;j++)
8848                         {
8849                                 float vertex[3];
8850                                 float *normal = rsurface.batchnormal3f + 3*j;
8851                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8852                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8853                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8854                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8855                                 VectorNormalize(normal);
8856                         }
8857                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8858                         {
8859 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8860 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8861 //                              rsurface.batchsvector3f_bufferoffset = 0;
8862 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8864 //                              rsurface.batchtvector3f_bufferoffset = 0;
8865                                 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);
8866                         }
8867                         break;
8868                 case Q3DEFORM_WAVE:
8869                         // deform vertex array to make wavey water and flags and such
8870                         waveparms[0] = deform->waveparms[0];
8871                         waveparms[1] = deform->waveparms[1];
8872                         waveparms[2] = deform->waveparms[2];
8873                         waveparms[3] = deform->waveparms[3];
8874                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8875                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8876                         // this is how a divisor of vertex influence on deformation
8877                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8878                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8879 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8880 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8881 //                      rsurface.batchvertex3f_bufferoffset = 0;
8882 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8883 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8884 //                      rsurface.batchnormal3f_bufferoffset = 0;
8885                         for (j = 0;j < batchnumvertices;j++)
8886                         {
8887                                 // if the wavefunc depends on time, evaluate it per-vertex
8888                                 if (waveparms[3])
8889                                 {
8890                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8891                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8892                                 }
8893                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8894                         }
8895                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8896                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8897                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8898                         {
8899 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8901 //                              rsurface.batchsvector3f_bufferoffset = 0;
8902 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8903 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8904 //                              rsurface.batchtvector3f_bufferoffset = 0;
8905                                 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);
8906                         }
8907                         break;
8908                 case Q3DEFORM_BULGE:
8909                         // deform vertex array to make the surface have moving bulges
8910 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8911 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8912 //                      rsurface.batchvertex3f_bufferoffset = 0;
8913 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8914 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8915 //                      rsurface.batchnormal3f_bufferoffset = 0;
8916                         for (j = 0;j < batchnumvertices;j++)
8917                         {
8918                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8919                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8920                         }
8921                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8922                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8923                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8924                         {
8925 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8926 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8927 //                              rsurface.batchsvector3f_bufferoffset = 0;
8928 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8929 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8930 //                              rsurface.batchtvector3f_bufferoffset = 0;
8931                                 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);
8932                         }
8933                         break;
8934                 case Q3DEFORM_MOVE:
8935                         // deform vertex array
8936                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8937                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8938                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8939                         VectorScale(deform->parms, scale, waveparms);
8940 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8941 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8942 //                      rsurface.batchvertex3f_bufferoffset = 0;
8943                         for (j = 0;j < batchnumvertices;j++)
8944                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8945                         break;
8946                 }
8947         }
8948
8949         // generate texcoords based on the chosen texcoord source
8950         switch(rsurface.texture->tcgen.tcgen)
8951         {
8952         default:
8953         case Q3TCGEN_TEXTURE:
8954                 break;
8955         case Q3TCGEN_LIGHTMAP:
8956 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8957 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8958 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8959                 if (rsurface.batchtexcoordlightmap2f)
8960                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8961                 break;
8962         case Q3TCGEN_VECTOR:
8963 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8964 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8965 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8966                 for (j = 0;j < batchnumvertices;j++)
8967                 {
8968                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8969                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8970                 }
8971                 break;
8972         case Q3TCGEN_ENVIRONMENT:
8973                 // make environment reflections using a spheremap
8974                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8975                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8976                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8977                 for (j = 0;j < batchnumvertices;j++)
8978                 {
8979                         // identical to Q3A's method, but executed in worldspace so
8980                         // carried models can be shiny too
8981
8982                         float viewer[3], d, reflected[3], worldreflected[3];
8983
8984                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8985                         // VectorNormalize(viewer);
8986
8987                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8988
8989                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8990                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8991                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8992                         // note: this is proportinal to viewer, so we can normalize later
8993
8994                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8995                         VectorNormalize(worldreflected);
8996
8997                         // note: this sphere map only uses world x and z!
8998                         // so positive and negative y will LOOK THE SAME.
8999                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9000                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9001                 }
9002                 break;
9003         }
9004         // the only tcmod that needs software vertex processing is turbulent, so
9005         // check for it here and apply the changes if needed
9006         // and we only support that as the first one
9007         // (handling a mixture of turbulent and other tcmods would be problematic
9008         //  without punting it entirely to a software path)
9009         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9010         {
9011                 amplitude = rsurface.texture->tcmods[0].parms[1];
9012                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9013 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9014 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9015 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9016                 for (j = 0;j < batchnumvertices;j++)
9017                 {
9018                         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);
9019                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9020                 }
9021         }
9022
9023         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9024         {
9025                 // convert the modified arrays to vertex structs
9026 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9027 //              rsurface.batchvertexmeshbuffer = NULL;
9028                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9029                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9030                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9031                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9032                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9033                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9034                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9035                 {
9036                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9037                         {
9038                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9039                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9040                         }
9041                 }
9042                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9043                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9044                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9045                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9046                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9047                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9048                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9049                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9050                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9051         }
9052 }
9053
9054 void RSurf_DrawBatch(void)
9055 {
9056         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9057         // through the pipeline, killing it earlier in the pipeline would have
9058         // per-surface overhead rather than per-batch overhead, so it's best to
9059         // reject it here, before it hits glDraw.
9060         if (rsurface.batchnumtriangles == 0)
9061                 return;
9062 #if 0
9063         // batch debugging code
9064         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9065         {
9066                 int i;
9067                 int j;
9068                 int c;
9069                 const int *e;
9070                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9071                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9072                 {
9073                         c = e[i];
9074                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9075                         {
9076                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9077                                 {
9078                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9079                                                 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);
9080                                         break;
9081                                 }
9082                         }
9083                 }
9084         }
9085 #endif
9086         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);
9087 }
9088
9089 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9090 {
9091         // pick the closest matching water plane
9092         int planeindex, vertexindex, bestplaneindex = -1;
9093         float d, bestd;
9094         vec3_t vert;
9095         const float *v;
9096         r_waterstate_waterplane_t *p;
9097         qboolean prepared = false;
9098         bestd = 0;
9099         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9100         {
9101                 if(p->camera_entity != rsurface.texture->camera_entity)
9102                         continue;
9103                 d = 0;
9104                 if(!prepared)
9105                 {
9106                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9107                         prepared = true;
9108                         if(rsurface.batchnumvertices == 0)
9109                                 break;
9110                 }
9111                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9112                 {
9113                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9114                         d += fabs(PlaneDiff(vert, &p->plane));
9115                 }
9116                 if (bestd > d || bestplaneindex < 0)
9117                 {
9118                         bestd = d;
9119                         bestplaneindex = planeindex;
9120                 }
9121         }
9122         return bestplaneindex;
9123         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9124         // this situation though, as it might be better to render single larger
9125         // batches with useless stuff (backface culled for example) than to
9126         // render multiple smaller batches
9127 }
9128
9129 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9130 {
9131         int i;
9132         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9133         rsurface.passcolor4f_vertexbuffer = 0;
9134         rsurface.passcolor4f_bufferoffset = 0;
9135         for (i = 0;i < rsurface.batchnumvertices;i++)
9136                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9137 }
9138
9139 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9140 {
9141         int i;
9142         float f;
9143         const float *v;
9144         const float *c;
9145         float *c2;
9146         if (rsurface.passcolor4f)
9147         {
9148                 // generate color arrays
9149                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9150                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9151                 rsurface.passcolor4f_vertexbuffer = 0;
9152                 rsurface.passcolor4f_bufferoffset = 0;
9153                 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)
9154                 {
9155                         f = RSurf_FogVertex(v);
9156                         c2[0] = c[0] * f;
9157                         c2[1] = c[1] * f;
9158                         c2[2] = c[2] * f;
9159                         c2[3] = c[3];
9160                 }
9161         }
9162         else
9163         {
9164                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9165                 rsurface.passcolor4f_vertexbuffer = 0;
9166                 rsurface.passcolor4f_bufferoffset = 0;
9167                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9168                 {
9169                         f = RSurf_FogVertex(v);
9170                         c2[0] = f;
9171                         c2[1] = f;
9172                         c2[2] = f;
9173                         c2[3] = 1;
9174                 }
9175         }
9176 }
9177
9178 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9179 {
9180         int i;
9181         float f;
9182         const float *v;
9183         const float *c;
9184         float *c2;
9185         if (!rsurface.passcolor4f)
9186                 return;
9187         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9188         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9189         rsurface.passcolor4f_vertexbuffer = 0;
9190         rsurface.passcolor4f_bufferoffset = 0;
9191         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)
9192         {
9193                 f = RSurf_FogVertex(v);
9194                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9195                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9196                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9197                 c2[3] = c[3];
9198         }
9199 }
9200
9201 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9202 {
9203         int i;
9204         const float *c;
9205         float *c2;
9206         if (!rsurface.passcolor4f)
9207                 return;
9208         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9209         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9210         rsurface.passcolor4f_vertexbuffer = 0;
9211         rsurface.passcolor4f_bufferoffset = 0;
9212         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9213         {
9214                 c2[0] = c[0] * r;
9215                 c2[1] = c[1] * g;
9216                 c2[2] = c[2] * b;
9217                 c2[3] = c[3] * a;
9218         }
9219 }
9220
9221 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9222 {
9223         int i;
9224         const float *c;
9225         float *c2;
9226         if (!rsurface.passcolor4f)
9227                 return;
9228         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9229         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9230         rsurface.passcolor4f_vertexbuffer = 0;
9231         rsurface.passcolor4f_bufferoffset = 0;
9232         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9233         {
9234                 c2[0] = c[0] + r_refdef.scene.ambient;
9235                 c2[1] = c[1] + r_refdef.scene.ambient;
9236                 c2[2] = c[2] + r_refdef.scene.ambient;
9237                 c2[3] = c[3];
9238         }
9239 }
9240
9241 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9242 {
9243         // TODO: optimize
9244         rsurface.passcolor4f = NULL;
9245         rsurface.passcolor4f_vertexbuffer = 0;
9246         rsurface.passcolor4f_bufferoffset = 0;
9247         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9248         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9249         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9250         GL_Color(r, g, b, a);
9251         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9252         RSurf_DrawBatch();
9253 }
9254
9255 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9256 {
9257         // TODO: optimize applyfog && applycolor case
9258         // just apply fog if necessary, and tint the fog color array if necessary
9259         rsurface.passcolor4f = NULL;
9260         rsurface.passcolor4f_vertexbuffer = 0;
9261         rsurface.passcolor4f_bufferoffset = 0;
9262         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9263         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9264         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9265         GL_Color(r, g, b, a);
9266         RSurf_DrawBatch();
9267 }
9268
9269 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9270 {
9271         // TODO: optimize
9272         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9273         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9274         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9275         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9276         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9277         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9278         GL_Color(r, g, b, a);
9279         RSurf_DrawBatch();
9280 }
9281
9282 static void RSurf_DrawBatch_GL11_ClampColor(void)
9283 {
9284         int i;
9285         const float *c1;
9286         float *c2;
9287         if (!rsurface.passcolor4f)
9288                 return;
9289         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9290         {
9291                 c2[0] = bound(0.0f, c1[0], 1.0f);
9292                 c2[1] = bound(0.0f, c1[1], 1.0f);
9293                 c2[2] = bound(0.0f, c1[2], 1.0f);
9294                 c2[3] = bound(0.0f, c1[3], 1.0f);
9295         }
9296 }
9297
9298 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9299 {
9300         int i;
9301         float f;
9302         const float *v;
9303         const float *n;
9304         float *c;
9305         //vec3_t eyedir;
9306
9307         // fake shading
9308         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9309         rsurface.passcolor4f_vertexbuffer = 0;
9310         rsurface.passcolor4f_bufferoffset = 0;
9311         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)
9312         {
9313                 f = -DotProduct(r_refdef.view.forward, n);
9314                 f = max(0, f);
9315                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9316                 f *= r_refdef.lightmapintensity;
9317                 Vector4Set(c, f, f, f, 1);
9318         }
9319 }
9320
9321 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9322 {
9323         RSurf_DrawBatch_GL11_ApplyFakeLight();
9324         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9325         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9326         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9327         GL_Color(r, g, b, a);
9328         RSurf_DrawBatch();
9329 }
9330
9331 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9332 {
9333         int i;
9334         float f;
9335         float alpha;
9336         const float *v;
9337         const float *n;
9338         float *c;
9339         vec3_t ambientcolor;
9340         vec3_t diffusecolor;
9341         vec3_t lightdir;
9342         // TODO: optimize
9343         // model lighting
9344         VectorCopy(rsurface.modellight_lightdir, lightdir);
9345         f = 0.5f * r_refdef.lightmapintensity;
9346         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9347         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9348         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9349         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9350         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9351         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9352         alpha = *a;
9353         if (VectorLength2(diffusecolor) > 0)
9354         {
9355                 // q3-style directional shading
9356                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9357                 rsurface.passcolor4f_vertexbuffer = 0;
9358                 rsurface.passcolor4f_bufferoffset = 0;
9359                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
9360                 {
9361                         if ((f = DotProduct(n, lightdir)) > 0)
9362                                 VectorMA(ambientcolor, f, diffusecolor, c);
9363                         else
9364                                 VectorCopy(ambientcolor, c);
9365                         c[3] = alpha;
9366                 }
9367                 *r = 1;
9368                 *g = 1;
9369                 *b = 1;
9370                 *a = 1;
9371                 *applycolor = false;
9372         }
9373         else
9374         {
9375                 *r = ambientcolor[0];
9376                 *g = ambientcolor[1];
9377                 *b = ambientcolor[2];
9378                 rsurface.passcolor4f = NULL;
9379                 rsurface.passcolor4f_vertexbuffer = 0;
9380                 rsurface.passcolor4f_bufferoffset = 0;
9381         }
9382 }
9383
9384 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9385 {
9386         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9387         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9388         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9389         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9390         GL_Color(r, g, b, a);
9391         RSurf_DrawBatch();
9392 }
9393
9394 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9395 {
9396         int i;
9397         float f;
9398         const float *v;
9399         float *c;
9400
9401         // fake shading
9402         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9403         rsurface.passcolor4f_vertexbuffer = 0;
9404         rsurface.passcolor4f_bufferoffset = 0;
9405
9406         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9407         {
9408                 f = 1 - RSurf_FogVertex(v);
9409                 c[0] = r;
9410                 c[1] = g;
9411                 c[2] = b;
9412                 c[3] = f * a;
9413         }
9414 }
9415
9416 void RSurf_SetupDepthAndCulling(void)
9417 {
9418         // submodels are biased to avoid z-fighting with world surfaces that they
9419         // may be exactly overlapping (avoids z-fighting artifacts on certain
9420         // doors and things in Quake maps)
9421         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9422         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9423         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9424         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9425 }
9426
9427 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9428 {
9429         // transparent sky would be ridiculous
9430         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9431                 return;
9432         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9433         skyrenderlater = true;
9434         RSurf_SetupDepthAndCulling();
9435         GL_DepthMask(true);
9436         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9437         // skymasking on them, and Quake3 never did sky masking (unlike
9438         // software Quake and software Quake2), so disable the sky masking
9439         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9440         // and skymasking also looks very bad when noclipping outside the
9441         // level, so don't use it then either.
9442         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9443         {
9444                 R_Mesh_ResetTextureState();
9445                 if (skyrendermasked)
9446                 {
9447                         R_SetupShader_DepthOrShadow();
9448                         // depth-only (masking)
9449                         GL_ColorMask(0,0,0,0);
9450                         // just to make sure that braindead drivers don't draw
9451                         // anything despite that colormask...
9452                         GL_BlendFunc(GL_ZERO, GL_ONE);
9453                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9454                         if (rsurface.batchvertex3fbuffer)
9455                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9456                         else
9457                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9458                 }
9459                 else
9460                 {
9461                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9462                         // fog sky
9463                         GL_BlendFunc(GL_ONE, GL_ZERO);
9464                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9465                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9466                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9467                 }
9468                 RSurf_DrawBatch();
9469                 if (skyrendermasked)
9470                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9471         }
9472         R_Mesh_ResetTextureState();
9473         GL_Color(1, 1, 1, 1);
9474 }
9475
9476 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9477 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9478 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9479 {
9480         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9481                 return;
9482         if (prepass)
9483         {
9484                 // render screenspace normalmap to texture
9485                 GL_DepthMask(true);
9486                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9487                 RSurf_DrawBatch();
9488         }
9489
9490         // bind lightmap texture
9491
9492         // water/refraction/reflection/camera surfaces have to be handled specially
9493         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9494         {
9495                 int start, end, startplaneindex;
9496                 for (start = 0;start < texturenumsurfaces;start = end)
9497                 {
9498                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9499                         if(startplaneindex < 0)
9500                         {
9501                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9502                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9503                                 end = start + 1;
9504                                 continue;
9505                         }
9506                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9507                                 ;
9508                         // now that we have a batch using the same planeindex, render it
9509                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9510                         {
9511                                 // render water or distortion background
9512                                 GL_DepthMask(true);
9513                                 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));
9514                                 RSurf_DrawBatch();
9515                                 // blend surface on top
9516                                 GL_DepthMask(false);
9517                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9518                                 RSurf_DrawBatch();
9519                         }
9520                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9521                         {
9522                                 // render surface with reflection texture as input
9523                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9524                                 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));
9525                                 RSurf_DrawBatch();
9526                         }
9527                 }
9528                 return;
9529         }
9530
9531         // render surface batch normally
9532         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9533         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9534         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9535                 GL_AlphaTest(true);
9536         RSurf_DrawBatch();
9537         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9538                 GL_AlphaTest(false);
9539 }
9540
9541 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9542 {
9543         // OpenGL 1.3 path - anything not completely ancient
9544         qboolean applycolor;
9545         qboolean applyfog;
9546         int layerindex;
9547         const texturelayer_t *layer;
9548         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);
9549         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9550
9551         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9552         {
9553                 vec4_t layercolor;
9554                 int layertexrgbscale;
9555                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9556                 {
9557                         if (layerindex == 0)
9558                                 GL_AlphaTest(true);
9559                         else
9560                         {
9561                                 GL_AlphaTest(false);
9562                                 GL_DepthFunc(GL_EQUAL);
9563                         }
9564                 }
9565                 GL_DepthMask(layer->depthmask && writedepth);
9566                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9567                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9568                 {
9569                         layertexrgbscale = 4;
9570                         VectorScale(layer->color, 0.25f, layercolor);
9571                 }
9572                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9573                 {
9574                         layertexrgbscale = 2;
9575                         VectorScale(layer->color, 0.5f, layercolor);
9576                 }
9577                 else
9578                 {
9579                         layertexrgbscale = 1;
9580                         VectorScale(layer->color, 1.0f, layercolor);
9581                 }
9582                 layercolor[3] = layer->color[3];
9583                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9584                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9585                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9586                 switch (layer->type)
9587                 {
9588                 case TEXTURELAYERTYPE_LITTEXTURE:
9589                         // single-pass lightmapped texture with 2x rgbscale
9590                         R_Mesh_TexBind(0, r_texture_white);
9591                         R_Mesh_TexMatrix(0, NULL);
9592                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9593                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9594                         R_Mesh_TexBind(1, layer->texture);
9595                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9596                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9597                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9598                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9599                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9600                         else if (FAKELIGHT_ENABLED)
9601                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9602                         else if (rsurface.uselightmaptexture)
9603                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9604                         else
9605                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9606                         break;
9607                 case TEXTURELAYERTYPE_TEXTURE:
9608                         // singletexture unlit texture with transparency support
9609                         R_Mesh_TexBind(0, layer->texture);
9610                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9611                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9612                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9613                         R_Mesh_TexBind(1, 0);
9614                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9615                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9616                         break;
9617                 case TEXTURELAYERTYPE_FOG:
9618                         // singletexture fogging
9619                         if (layer->texture)
9620                         {
9621                                 R_Mesh_TexBind(0, layer->texture);
9622                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9623                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9624                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9625                         }
9626                         else
9627                         {
9628                                 R_Mesh_TexBind(0, 0);
9629                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9630                         }
9631                         R_Mesh_TexBind(1, 0);
9632                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9633                         // generate a color array for the fog pass
9634                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9635                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9636                         RSurf_DrawBatch();
9637                         break;
9638                 default:
9639                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9640                 }
9641         }
9642         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9643         {
9644                 GL_DepthFunc(GL_LEQUAL);
9645                 GL_AlphaTest(false);
9646         }
9647 }
9648
9649 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9650 {
9651         // OpenGL 1.1 - crusty old voodoo path
9652         qboolean applyfog;
9653         int layerindex;
9654         const texturelayer_t *layer;
9655         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);
9656         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9657
9658         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9659         {
9660                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9661                 {
9662                         if (layerindex == 0)
9663                                 GL_AlphaTest(true);
9664                         else
9665                         {
9666                                 GL_AlphaTest(false);
9667                                 GL_DepthFunc(GL_EQUAL);
9668                         }
9669                 }
9670                 GL_DepthMask(layer->depthmask && writedepth);
9671                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9672                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9673                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9674                 switch (layer->type)
9675                 {
9676                 case TEXTURELAYERTYPE_LITTEXTURE:
9677                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9678                         {
9679                                 // two-pass lit texture with 2x rgbscale
9680                                 // first the lightmap pass
9681                                 R_Mesh_TexBind(0, r_texture_white);
9682                                 R_Mesh_TexMatrix(0, NULL);
9683                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9684                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9685                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9686                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9687                                 else if (FAKELIGHT_ENABLED)
9688                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9689                                 else if (rsurface.uselightmaptexture)
9690                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9691                                 else
9692                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9693                                 // then apply the texture to it
9694                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9695                                 R_Mesh_TexBind(0, layer->texture);
9696                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9697                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9698                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9699                                 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);
9700                         }
9701                         else
9702                         {
9703                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9704                                 R_Mesh_TexBind(0, layer->texture);
9705                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9706                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9707                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9708                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9709                                         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);
9710                                 else
9711                                         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);
9712                         }
9713                         break;
9714                 case TEXTURELAYERTYPE_TEXTURE:
9715                         // singletexture unlit texture with transparency support
9716                         R_Mesh_TexBind(0, layer->texture);
9717                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9718                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9719                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9720                         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);
9721                         break;
9722                 case TEXTURELAYERTYPE_FOG:
9723                         // singletexture fogging
9724                         if (layer->texture)
9725                         {
9726                                 R_Mesh_TexBind(0, layer->texture);
9727                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9728                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9729                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9730                         }
9731                         else
9732                         {
9733                                 R_Mesh_TexBind(0, 0);
9734                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9735                         }
9736                         // generate a color array for the fog pass
9737                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9738                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9739                         RSurf_DrawBatch();
9740                         break;
9741                 default:
9742                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9743                 }
9744         }
9745         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9746         {
9747                 GL_DepthFunc(GL_LEQUAL);
9748                 GL_AlphaTest(false);
9749         }
9750 }
9751
9752 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9753 {
9754         int vi;
9755         int j;
9756         r_vertexgeneric_t *batchvertex;
9757         float c[4];
9758
9759 //      R_Mesh_ResetTextureState();
9760         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9761
9762         if(rsurface.texture && rsurface.texture->currentskinframe)
9763         {
9764                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9765                 c[3] *= rsurface.texture->currentalpha;
9766         }
9767         else
9768         {
9769                 c[0] = 1;
9770                 c[1] = 0;
9771                 c[2] = 1;
9772                 c[3] = 1;
9773         }
9774
9775         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9776         {
9777                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9778                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9779                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9780         }
9781
9782         // brighten it up (as texture value 127 means "unlit")
9783         c[0] *= 2 * r_refdef.view.colorscale;
9784         c[1] *= 2 * r_refdef.view.colorscale;
9785         c[2] *= 2 * r_refdef.view.colorscale;
9786
9787         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9788                 c[3] *= r_wateralpha.value;
9789
9790         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9791         {
9792                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9793                 GL_DepthMask(false);
9794         }
9795         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9796         {
9797                 GL_BlendFunc(GL_ONE, GL_ONE);
9798                 GL_DepthMask(false);
9799         }
9800         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9801         {
9802                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9803                 GL_DepthMask(false);
9804         }
9805         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9806         {
9807                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9808                 GL_DepthMask(false);
9809         }
9810         else
9811         {
9812                 GL_BlendFunc(GL_ONE, GL_ZERO);
9813                 GL_DepthMask(writedepth);
9814         }
9815
9816         if (r_showsurfaces.integer == 3)
9817         {
9818                 rsurface.passcolor4f = NULL;
9819
9820                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9821                 {
9822                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9823
9824                         rsurface.passcolor4f = NULL;
9825                         rsurface.passcolor4f_vertexbuffer = 0;
9826                         rsurface.passcolor4f_bufferoffset = 0;
9827                 }
9828                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9829                 {
9830                         qboolean applycolor = true;
9831                         float one = 1.0;
9832
9833                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9834
9835                         r_refdef.lightmapintensity = 1;
9836                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9837                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9838                 }
9839                 else if (FAKELIGHT_ENABLED)
9840                 {
9841                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9842
9843                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9844                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9845                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9846                 }
9847                 else
9848                 {
9849                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9850
9851                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9852                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9853                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9854                 }
9855
9856                 if(!rsurface.passcolor4f)
9857                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9858
9859                 RSurf_DrawBatch_GL11_ApplyAmbient();
9860                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9861                 if(r_refdef.fogenabled)
9862                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9863                 RSurf_DrawBatch_GL11_ClampColor();
9864
9865                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9866                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9867                 RSurf_DrawBatch();
9868         }
9869         else if (!r_refdef.view.showdebug)
9870         {
9871                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9872                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9873                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9874                 {
9875                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9876                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9877                 }
9878                 R_Mesh_PrepareVertices_Generic_Unlock();
9879                 RSurf_DrawBatch();
9880         }
9881         else if (r_showsurfaces.integer == 4)
9882         {
9883                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9884                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9885                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9886                 {
9887                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9888                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9889                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9890                 }
9891                 R_Mesh_PrepareVertices_Generic_Unlock();
9892                 RSurf_DrawBatch();
9893         }
9894         else if (r_showsurfaces.integer == 2)
9895         {
9896                 const int *e;
9897                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9898                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9899                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9900                 {
9901                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9902                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9903                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9904                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9905                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9906                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9907                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9908                 }
9909                 R_Mesh_PrepareVertices_Generic_Unlock();
9910                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9911         }
9912         else
9913         {
9914                 int texturesurfaceindex;
9915                 int k;
9916                 const msurface_t *surface;
9917                 float surfacecolor4f[4];
9918                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9919                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9920                 vi = 0;
9921                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9922                 {
9923                         surface = texturesurfacelist[texturesurfaceindex];
9924                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9925                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9926                         for (j = 0;j < surface->num_vertices;j++)
9927                         {
9928                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9929                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9930                                 vi++;
9931                         }
9932                 }
9933                 R_Mesh_PrepareVertices_Generic_Unlock();
9934                 RSurf_DrawBatch();
9935         }
9936 }
9937
9938 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9939 {
9940         CHECKGLERROR
9941         RSurf_SetupDepthAndCulling();
9942         if (r_showsurfaces.integer)
9943         {
9944                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9945                 return;
9946         }
9947         switch (vid.renderpath)
9948         {
9949         case RENDERPATH_GL20:
9950         case RENDERPATH_D3D9:
9951         case RENDERPATH_D3D10:
9952         case RENDERPATH_D3D11:
9953         case RENDERPATH_SOFT:
9954         case RENDERPATH_GLES2:
9955                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9956                 break;
9957         case RENDERPATH_GL13:
9958         case RENDERPATH_GLES1:
9959                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9960                 break;
9961         case RENDERPATH_GL11:
9962                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9963                 break;
9964         }
9965         CHECKGLERROR
9966 }
9967
9968 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9969 {
9970         CHECKGLERROR
9971         RSurf_SetupDepthAndCulling();
9972         if (r_showsurfaces.integer)
9973         {
9974                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9975                 return;
9976         }
9977         switch (vid.renderpath)
9978         {
9979         case RENDERPATH_GL20:
9980         case RENDERPATH_D3D9:
9981         case RENDERPATH_D3D10:
9982         case RENDERPATH_D3D11:
9983         case RENDERPATH_SOFT:
9984         case RENDERPATH_GLES2:
9985                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9986                 break;
9987         case RENDERPATH_GL13:
9988         case RENDERPATH_GLES1:
9989                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9990                 break;
9991         case RENDERPATH_GL11:
9992                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9993                 break;
9994         }
9995         CHECKGLERROR
9996 }
9997
9998 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9999 {
10000         int i, j;
10001         int texturenumsurfaces, endsurface;
10002         texture_t *texture;
10003         const msurface_t *surface;
10004         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10005
10006         // if the model is static it doesn't matter what value we give for
10007         // wantnormals and wanttangents, so this logic uses only rules applicable
10008         // to a model, knowing that they are meaningless otherwise
10009         if (ent == r_refdef.scene.worldentity)
10010                 RSurf_ActiveWorldEntity();
10011         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10012                 RSurf_ActiveModelEntity(ent, false, false, false);
10013         else
10014         {
10015                 switch (vid.renderpath)
10016                 {
10017                 case RENDERPATH_GL20:
10018                 case RENDERPATH_D3D9:
10019                 case RENDERPATH_D3D10:
10020                 case RENDERPATH_D3D11:
10021                 case RENDERPATH_SOFT:
10022                 case RENDERPATH_GLES2:
10023                         RSurf_ActiveModelEntity(ent, true, true, false);
10024                         break;
10025                 case RENDERPATH_GL11:
10026                 case RENDERPATH_GL13:
10027                 case RENDERPATH_GLES1:
10028                         RSurf_ActiveModelEntity(ent, true, false, false);
10029                         break;
10030                 }
10031         }
10032
10033         if (r_transparentdepthmasking.integer)
10034         {
10035                 qboolean setup = false;
10036                 for (i = 0;i < numsurfaces;i = j)
10037                 {
10038                         j = i + 1;
10039                         surface = rsurface.modelsurfaces + surfacelist[i];
10040                         texture = surface->texture;
10041                         rsurface.texture = R_GetCurrentTexture(texture);
10042                         rsurface.lightmaptexture = NULL;
10043                         rsurface.deluxemaptexture = NULL;
10044                         rsurface.uselightmaptexture = false;
10045                         // scan ahead until we find a different texture
10046                         endsurface = min(i + 1024, numsurfaces);
10047                         texturenumsurfaces = 0;
10048                         texturesurfacelist[texturenumsurfaces++] = surface;
10049                         for (;j < endsurface;j++)
10050                         {
10051                                 surface = rsurface.modelsurfaces + surfacelist[j];
10052                                 if (texture != surface->texture)
10053                                         break;
10054                                 texturesurfacelist[texturenumsurfaces++] = surface;
10055                         }
10056                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10057                                 continue;
10058                         // render the range of surfaces as depth
10059                         if (!setup)
10060                         {
10061                                 setup = true;
10062                                 GL_ColorMask(0,0,0,0);
10063                                 GL_Color(1,1,1,1);
10064                                 GL_DepthTest(true);
10065                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10066                                 GL_DepthMask(true);
10067 //                              R_Mesh_ResetTextureState();
10068                                 R_SetupShader_DepthOrShadow();
10069                         }
10070                         RSurf_SetupDepthAndCulling();
10071                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10072                         if (rsurface.batchvertex3fbuffer)
10073                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10074                         else
10075                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10076                         RSurf_DrawBatch();
10077                 }
10078                 if (setup)
10079                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10080         }
10081
10082         for (i = 0;i < numsurfaces;i = j)
10083         {
10084                 j = i + 1;
10085                 surface = rsurface.modelsurfaces + surfacelist[i];
10086                 texture = surface->texture;
10087                 rsurface.texture = R_GetCurrentTexture(texture);
10088                 // scan ahead until we find a different texture
10089                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10090                 texturenumsurfaces = 0;
10091                 texturesurfacelist[texturenumsurfaces++] = surface;
10092                 if(FAKELIGHT_ENABLED)
10093                 {
10094                         rsurface.lightmaptexture = NULL;
10095                         rsurface.deluxemaptexture = NULL;
10096                         rsurface.uselightmaptexture = false;
10097                         for (;j < endsurface;j++)
10098                         {
10099                                 surface = rsurface.modelsurfaces + surfacelist[j];
10100                                 if (texture != surface->texture)
10101                                         break;
10102                                 texturesurfacelist[texturenumsurfaces++] = surface;
10103                         }
10104                 }
10105                 else
10106                 {
10107                         rsurface.lightmaptexture = surface->lightmaptexture;
10108                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10109                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10110                         for (;j < endsurface;j++)
10111                         {
10112                                 surface = rsurface.modelsurfaces + surfacelist[j];
10113                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10114                                         break;
10115                                 texturesurfacelist[texturenumsurfaces++] = surface;
10116                         }
10117                 }
10118                 // render the range of surfaces
10119                 if (ent == r_refdef.scene.worldentity)
10120                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10121                 else
10122                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10123         }
10124         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10125 }
10126
10127 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10128 {
10129         // transparent surfaces get pushed off into the transparent queue
10130         int surfacelistindex;
10131         const msurface_t *surface;
10132         vec3_t tempcenter, center;
10133         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10134         {
10135                 surface = texturesurfacelist[surfacelistindex];
10136                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10137                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10138                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10139                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10140                 if (queueentity->transparent_offset) // transparent offset
10141                 {
10142                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10143                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10144                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10145                 }
10146                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10147         }
10148 }
10149
10150 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10151 {
10152         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10153                 return;
10154         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10155                 return;
10156         RSurf_SetupDepthAndCulling();
10157         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10158         if (rsurface.batchvertex3fbuffer)
10159                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10160         else
10161                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10162         RSurf_DrawBatch();
10163 }
10164
10165 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10166 {
10167         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10168         CHECKGLERROR
10169         if (depthonly)
10170                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10171         else if (prepass)
10172         {
10173                 if (!rsurface.texture->currentnumlayers)
10174                         return;
10175                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10176                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10177                 else
10178                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10179         }
10180         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10181                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10182         else if (!rsurface.texture->currentnumlayers)
10183                 return;
10184         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10185         {
10186                 // in the deferred case, transparent surfaces were queued during prepass
10187                 if (!r_shadow_usingdeferredprepass)
10188                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10189         }
10190         else
10191         {
10192                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10193                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10194         }
10195         CHECKGLERROR
10196 }
10197
10198 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10199 {
10200         int i, j;
10201         texture_t *texture;
10202         R_FrameData_SetMark();
10203         // break the surface list down into batches by texture and use of lightmapping
10204         for (i = 0;i < numsurfaces;i = j)
10205         {
10206                 j = i + 1;
10207                 // texture is the base texture pointer, rsurface.texture is the
10208                 // current frame/skin the texture is directing us to use (for example
10209                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10210                 // use skin 1 instead)
10211                 texture = surfacelist[i]->texture;
10212                 rsurface.texture = R_GetCurrentTexture(texture);
10213                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10214                 {
10215                         // if this texture is not the kind we want, skip ahead to the next one
10216                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10217                                 ;
10218                         continue;
10219                 }
10220                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10221                 {
10222                         rsurface.lightmaptexture = NULL;
10223                         rsurface.deluxemaptexture = NULL;
10224                         rsurface.uselightmaptexture = false;
10225                         // simply scan ahead until we find a different texture or lightmap state
10226                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10227                                 ;
10228                 }
10229                 else
10230                 {
10231                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10232                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10233                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10234                         // simply scan ahead until we find a different texture or lightmap state
10235                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10236                                 ;
10237                 }
10238                 // render the range of surfaces
10239                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10240         }
10241         R_FrameData_ReturnToMark();
10242 }
10243
10244 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10245 {
10246         CHECKGLERROR
10247         if (depthonly)
10248                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10249         else if (prepass)
10250         {
10251                 if (!rsurface.texture->currentnumlayers)
10252                         return;
10253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10254                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10255                 else
10256                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10257         }
10258         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10259                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10260         else if (!rsurface.texture->currentnumlayers)
10261                 return;
10262         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10263         {
10264                 // in the deferred case, transparent surfaces were queued during prepass
10265                 if (!r_shadow_usingdeferredprepass)
10266                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10267         }
10268         else
10269         {
10270                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10271                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10272         }
10273         CHECKGLERROR
10274 }
10275
10276 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10277 {
10278         int i, j;
10279         texture_t *texture;
10280         R_FrameData_SetMark();
10281         // break the surface list down into batches by texture and use of lightmapping
10282         for (i = 0;i < numsurfaces;i = j)
10283         {
10284                 j = i + 1;
10285                 // texture is the base texture pointer, rsurface.texture is the
10286                 // current frame/skin the texture is directing us to use (for example
10287                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10288                 // use skin 1 instead)
10289                 texture = surfacelist[i]->texture;
10290                 rsurface.texture = R_GetCurrentTexture(texture);
10291                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10292                 {
10293                         // if this texture is not the kind we want, skip ahead to the next one
10294                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10295                                 ;
10296                         continue;
10297                 }
10298                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10299                 {
10300                         rsurface.lightmaptexture = NULL;
10301                         rsurface.deluxemaptexture = NULL;
10302                         rsurface.uselightmaptexture = false;
10303                         // simply scan ahead until we find a different texture or lightmap state
10304                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10305                                 ;
10306                 }
10307                 else
10308                 {
10309                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10310                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10311                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10312                         // simply scan ahead until we find a different texture or lightmap state
10313                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10314                                 ;
10315                 }
10316                 // render the range of surfaces
10317                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10318         }
10319         R_FrameData_ReturnToMark();
10320 }
10321
10322 float locboxvertex3f[6*4*3] =
10323 {
10324         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10325         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10326         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10327         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10328         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10329         1,0,0, 0,0,0, 0,1,0, 1,1,0
10330 };
10331
10332 unsigned short locboxelements[6*2*3] =
10333 {
10334          0, 1, 2, 0, 2, 3,
10335          4, 5, 6, 4, 6, 7,
10336          8, 9,10, 8,10,11,
10337         12,13,14, 12,14,15,
10338         16,17,18, 16,18,19,
10339         20,21,22, 20,22,23
10340 };
10341
10342 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10343 {
10344         int i, j;
10345         cl_locnode_t *loc = (cl_locnode_t *)ent;
10346         vec3_t mins, size;
10347         float vertex3f[6*4*3];
10348         CHECKGLERROR
10349         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10350         GL_DepthMask(false);
10351         GL_DepthRange(0, 1);
10352         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10353         GL_DepthTest(true);
10354         GL_CullFace(GL_NONE);
10355         R_EntityMatrix(&identitymatrix);
10356
10357 //      R_Mesh_ResetTextureState();
10358
10359         i = surfacelist[0];
10360         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10361                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10362                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10363                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10364
10365         if (VectorCompare(loc->mins, loc->maxs))
10366         {
10367                 VectorSet(size, 2, 2, 2);
10368                 VectorMA(loc->mins, -0.5f, size, mins);
10369         }
10370         else
10371         {
10372                 VectorCopy(loc->mins, mins);
10373                 VectorSubtract(loc->maxs, loc->mins, size);
10374         }
10375
10376         for (i = 0;i < 6*4*3;)
10377                 for (j = 0;j < 3;j++, i++)
10378                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10379
10380         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10381         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10382         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10383 }
10384
10385 void R_DrawLocs(void)
10386 {
10387         int index;
10388         cl_locnode_t *loc, *nearestloc;
10389         vec3_t center;
10390         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10391         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10392         {
10393                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10394                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10395         }
10396 }
10397
10398 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10399 {
10400         if (decalsystem->decals)
10401                 Mem_Free(decalsystem->decals);
10402         memset(decalsystem, 0, sizeof(*decalsystem));
10403 }
10404
10405 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)
10406 {
10407         tridecal_t *decal;
10408         tridecal_t *decals;
10409         int i;
10410
10411         // expand or initialize the system
10412         if (decalsystem->maxdecals <= decalsystem->numdecals)
10413         {
10414                 decalsystem_t old = *decalsystem;
10415                 qboolean useshortelements;
10416                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10417                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10418                 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)));
10419                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10420                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10421                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10422                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10423                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10424                 if (decalsystem->numdecals)
10425                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10426                 if (old.decals)
10427                         Mem_Free(old.decals);
10428                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10429                         decalsystem->element3i[i] = i;
10430                 if (useshortelements)
10431                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10432                                 decalsystem->element3s[i] = i;
10433         }
10434
10435         // grab a decal and search for another free slot for the next one
10436         decals = decalsystem->decals;
10437         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10438         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10439                 ;
10440         decalsystem->freedecal = i;
10441         if (decalsystem->numdecals <= i)
10442                 decalsystem->numdecals = i + 1;
10443
10444         // initialize the decal
10445         decal->lived = 0;
10446         decal->triangleindex = triangleindex;
10447         decal->surfaceindex = surfaceindex;
10448         decal->decalsequence = decalsequence;
10449         decal->color4f[0][0] = c0[0];
10450         decal->color4f[0][1] = c0[1];
10451         decal->color4f[0][2] = c0[2];
10452         decal->color4f[0][3] = 1;
10453         decal->color4f[1][0] = c1[0];
10454         decal->color4f[1][1] = c1[1];
10455         decal->color4f[1][2] = c1[2];
10456         decal->color4f[1][3] = 1;
10457         decal->color4f[2][0] = c2[0];
10458         decal->color4f[2][1] = c2[1];
10459         decal->color4f[2][2] = c2[2];
10460         decal->color4f[2][3] = 1;
10461         decal->vertex3f[0][0] = v0[0];
10462         decal->vertex3f[0][1] = v0[1];
10463         decal->vertex3f[0][2] = v0[2];
10464         decal->vertex3f[1][0] = v1[0];
10465         decal->vertex3f[1][1] = v1[1];
10466         decal->vertex3f[1][2] = v1[2];
10467         decal->vertex3f[2][0] = v2[0];
10468         decal->vertex3f[2][1] = v2[1];
10469         decal->vertex3f[2][2] = v2[2];
10470         decal->texcoord2f[0][0] = t0[0];
10471         decal->texcoord2f[0][1] = t0[1];
10472         decal->texcoord2f[1][0] = t1[0];
10473         decal->texcoord2f[1][1] = t1[1];
10474         decal->texcoord2f[2][0] = t2[0];
10475         decal->texcoord2f[2][1] = t2[1];
10476         TriangleNormal(v0, v1, v2, decal->plane);
10477         VectorNormalize(decal->plane);
10478         decal->plane[3] = DotProduct(v0, decal->plane);
10479 }
10480
10481 extern cvar_t cl_decals_bias;
10482 extern cvar_t cl_decals_models;
10483 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10484 // baseparms, parms, temps
10485 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)
10486 {
10487         int cornerindex;
10488         int index;
10489         float v[9][3];
10490         const float *vertex3f;
10491         const float *normal3f;
10492         int numpoints;
10493         float points[2][9][3];
10494         float temp[3];
10495         float tc[9][2];
10496         float f;
10497         float c[9][4];
10498         const int *e;
10499
10500         e = rsurface.modelelement3i + 3*triangleindex;
10501
10502         vertex3f = rsurface.modelvertex3f;
10503         normal3f = rsurface.modelnormal3f;
10504
10505         if (normal3f)
10506         {
10507                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10508                 {
10509                         index = 3*e[cornerindex];
10510                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10511                 }
10512         }
10513         else
10514         {
10515                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10516                 {
10517                         index = 3*e[cornerindex];
10518                         VectorCopy(vertex3f + index, v[cornerindex]);
10519                 }
10520         }
10521
10522         // cull backfaces
10523         //TriangleNormal(v[0], v[1], v[2], normal);
10524         //if (DotProduct(normal, localnormal) < 0.0f)
10525         //      continue;
10526         // clip by each of the box planes formed from the projection matrix
10527         // if anything survives, we emit the decal
10528         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]);
10529         if (numpoints < 3)
10530                 return;
10531         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]);
10532         if (numpoints < 3)
10533                 return;
10534         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]);
10535         if (numpoints < 3)
10536                 return;
10537         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]);
10538         if (numpoints < 3)
10539                 return;
10540         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]);
10541         if (numpoints < 3)
10542                 return;
10543         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]);
10544         if (numpoints < 3)
10545                 return;
10546         // some part of the triangle survived, so we have to accept it...
10547         if (dynamic)
10548         {
10549                 // dynamic always uses the original triangle
10550                 numpoints = 3;
10551                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10552                 {
10553                         index = 3*e[cornerindex];
10554                         VectorCopy(vertex3f + index, v[cornerindex]);
10555                 }
10556         }
10557         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10558         {
10559                 // convert vertex positions to texcoords
10560                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10561                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10562                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10563                 // calculate distance fade from the projection origin
10564                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10565                 f = bound(0.0f, f, 1.0f);
10566                 c[cornerindex][0] = r * f;
10567                 c[cornerindex][1] = g * f;
10568                 c[cornerindex][2] = b * f;
10569                 c[cornerindex][3] = 1.0f;
10570                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10571         }
10572         if (dynamic)
10573                 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);
10574         else
10575                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10576                         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);
10577 }
10578 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)
10579 {
10580         matrix4x4_t projection;
10581         decalsystem_t *decalsystem;
10582         qboolean dynamic;
10583         dp_model_t *model;
10584         const msurface_t *surface;
10585         const msurface_t *surfaces;
10586         const int *surfacelist;
10587         const texture_t *texture;
10588         int numtriangles;
10589         int numsurfacelist;
10590         int surfacelistindex;
10591         int surfaceindex;
10592         int triangleindex;
10593         float localorigin[3];
10594         float localnormal[3];
10595         float localmins[3];
10596         float localmaxs[3];
10597         float localsize;
10598         //float normal[3];
10599         float planes[6][4];
10600         float angles[3];
10601         bih_t *bih;
10602         int bih_triangles_count;
10603         int bih_triangles[256];
10604         int bih_surfaces[256];
10605
10606         decalsystem = &ent->decalsystem;
10607         model = ent->model;
10608         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10609         {
10610                 R_DecalSystem_Reset(&ent->decalsystem);
10611                 return;
10612         }
10613
10614         if (!model->brush.data_leafs && !cl_decals_models.integer)
10615         {
10616                 if (decalsystem->model)
10617                         R_DecalSystem_Reset(decalsystem);
10618                 return;
10619         }
10620
10621         if (decalsystem->model != model)
10622                 R_DecalSystem_Reset(decalsystem);
10623         decalsystem->model = model;
10624
10625         RSurf_ActiveModelEntity(ent, true, false, false);
10626
10627         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10628         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10629         VectorNormalize(localnormal);
10630         localsize = worldsize*rsurface.inversematrixscale;
10631         localmins[0] = localorigin[0] - localsize;
10632         localmins[1] = localorigin[1] - localsize;
10633         localmins[2] = localorigin[2] - localsize;
10634         localmaxs[0] = localorigin[0] + localsize;
10635         localmaxs[1] = localorigin[1] + localsize;
10636         localmaxs[2] = localorigin[2] + localsize;
10637
10638         //VectorCopy(localnormal, planes[4]);
10639         //VectorVectors(planes[4], planes[2], planes[0]);
10640         AnglesFromVectors(angles, localnormal, NULL, false);
10641         AngleVectors(angles, planes[0], planes[2], planes[4]);
10642         VectorNegate(planes[0], planes[1]);
10643         VectorNegate(planes[2], planes[3]);
10644         VectorNegate(planes[4], planes[5]);
10645         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10646         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10647         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10648         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10649         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10650         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10651
10652 #if 1
10653 // works
10654 {
10655         matrix4x4_t forwardprojection;
10656         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10657         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10658 }
10659 #else
10660 // broken
10661 {
10662         float projectionvector[4][3];
10663         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10664         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10665         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10666         projectionvector[0][0] = planes[0][0] * ilocalsize;
10667         projectionvector[0][1] = planes[1][0] * ilocalsize;
10668         projectionvector[0][2] = planes[2][0] * ilocalsize;
10669         projectionvector[1][0] = planes[0][1] * ilocalsize;
10670         projectionvector[1][1] = planes[1][1] * ilocalsize;
10671         projectionvector[1][2] = planes[2][1] * ilocalsize;
10672         projectionvector[2][0] = planes[0][2] * ilocalsize;
10673         projectionvector[2][1] = planes[1][2] * ilocalsize;
10674         projectionvector[2][2] = planes[2][2] * ilocalsize;
10675         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10676         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10677         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10678         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10679 }
10680 #endif
10681
10682         dynamic = model->surfmesh.isanimated;
10683         numsurfacelist = model->nummodelsurfaces;
10684         surfacelist = model->sortedmodelsurfaces;
10685         surfaces = model->data_surfaces;
10686
10687         bih = NULL;
10688         bih_triangles_count = -1;
10689         if(!dynamic)
10690         {
10691                 if(model->render_bih.numleafs)
10692                         bih = &model->render_bih;
10693                 else if(model->collision_bih.numleafs)
10694                         bih = &model->collision_bih;
10695         }
10696         if(bih)
10697                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10698         if(bih_triangles_count == 0)
10699                 return;
10700         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10701                 return;
10702         if(bih_triangles_count > 0)
10703         {
10704                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10705                 {
10706                         surfaceindex = bih_surfaces[triangleindex];
10707                         surface = surfaces + surfaceindex;
10708                         texture = surface->texture;
10709                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10710                                 continue;
10711                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10712                                 continue;
10713                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10714                 }
10715         }
10716         else
10717         {
10718                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10719                 {
10720                         surfaceindex = surfacelist[surfacelistindex];
10721                         surface = surfaces + surfaceindex;
10722                         // check cull box first because it rejects more than any other check
10723                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10724                                 continue;
10725                         // skip transparent surfaces
10726                         texture = surface->texture;
10727                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10728                                 continue;
10729                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10730                                 continue;
10731                         numtriangles = surface->num_triangles;
10732                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10733                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10734                 }
10735         }
10736 }
10737
10738 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10739 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)
10740 {
10741         int renderentityindex;
10742         float worldmins[3];
10743         float worldmaxs[3];
10744         entity_render_t *ent;
10745
10746         if (!cl_decals_newsystem.integer)
10747                 return;
10748
10749         worldmins[0] = worldorigin[0] - worldsize;
10750         worldmins[1] = worldorigin[1] - worldsize;
10751         worldmins[2] = worldorigin[2] - worldsize;
10752         worldmaxs[0] = worldorigin[0] + worldsize;
10753         worldmaxs[1] = worldorigin[1] + worldsize;
10754         worldmaxs[2] = worldorigin[2] + worldsize;
10755
10756         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10757
10758         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10759         {
10760                 ent = r_refdef.scene.entities[renderentityindex];
10761                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10762                         continue;
10763
10764                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10765         }
10766 }
10767
10768 typedef struct r_decalsystem_splatqueue_s
10769 {
10770         vec3_t worldorigin;
10771         vec3_t worldnormal;
10772         float color[4];
10773         float tcrange[4];
10774         float worldsize;
10775         int decalsequence;
10776 }
10777 r_decalsystem_splatqueue_t;
10778
10779 int r_decalsystem_numqueued = 0;
10780 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10781
10782 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)
10783 {
10784         r_decalsystem_splatqueue_t *queue;
10785
10786         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10787                 return;
10788
10789         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10790         VectorCopy(worldorigin, queue->worldorigin);
10791         VectorCopy(worldnormal, queue->worldnormal);
10792         Vector4Set(queue->color, r, g, b, a);
10793         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10794         queue->worldsize = worldsize;
10795         queue->decalsequence = cl.decalsequence++;
10796 }
10797
10798 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10799 {
10800         int i;
10801         r_decalsystem_splatqueue_t *queue;
10802
10803         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10804                 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);
10805         r_decalsystem_numqueued = 0;
10806 }
10807
10808 extern cvar_t cl_decals_max;
10809 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10810 {
10811         int i;
10812         decalsystem_t *decalsystem = &ent->decalsystem;
10813         int numdecals;
10814         int killsequence;
10815         tridecal_t *decal;
10816         float frametime;
10817         float lifetime;
10818
10819         if (!decalsystem->numdecals)
10820                 return;
10821
10822         if (r_showsurfaces.integer)
10823                 return;
10824
10825         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10826         {
10827                 R_DecalSystem_Reset(decalsystem);
10828                 return;
10829         }
10830
10831         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10832         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10833
10834         if (decalsystem->lastupdatetime)
10835                 frametime = (cl.time - decalsystem->lastupdatetime);
10836         else
10837                 frametime = 0;
10838         decalsystem->lastupdatetime = cl.time;
10839         decal = decalsystem->decals;
10840         numdecals = decalsystem->numdecals;
10841
10842         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10843         {
10844                 if (decal->color4f[0][3])
10845                 {
10846                         decal->lived += frametime;
10847                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10848                         {
10849                                 memset(decal, 0, sizeof(*decal));
10850                                 if (decalsystem->freedecal > i)
10851                                         decalsystem->freedecal = i;
10852                         }
10853                 }
10854         }
10855         decal = decalsystem->decals;
10856         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10857                 numdecals--;
10858
10859         // collapse the array by shuffling the tail decals into the gaps
10860         for (;;)
10861         {
10862                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10863                         decalsystem->freedecal++;
10864                 if (decalsystem->freedecal == numdecals)
10865                         break;
10866                 decal[decalsystem->freedecal] = decal[--numdecals];
10867         }
10868
10869         decalsystem->numdecals = numdecals;
10870
10871         if (numdecals <= 0)
10872         {
10873                 // if there are no decals left, reset decalsystem
10874                 R_DecalSystem_Reset(decalsystem);
10875         }
10876 }
10877
10878 extern skinframe_t *decalskinframe;
10879 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10880 {
10881         int i;
10882         decalsystem_t *decalsystem = &ent->decalsystem;
10883         int numdecals;
10884         tridecal_t *decal;
10885         float faderate;
10886         float alpha;
10887         float *v3f;
10888         float *c4f;
10889         float *t2f;
10890         const int *e;
10891         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10892         int numtris = 0;
10893
10894         numdecals = decalsystem->numdecals;
10895         if (!numdecals)
10896                 return;
10897
10898         if (r_showsurfaces.integer)
10899                 return;
10900
10901         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10902         {
10903                 R_DecalSystem_Reset(decalsystem);
10904                 return;
10905         }
10906
10907         // if the model is static it doesn't matter what value we give for
10908         // wantnormals and wanttangents, so this logic uses only rules applicable
10909         // to a model, knowing that they are meaningless otherwise
10910         if (ent == r_refdef.scene.worldentity)
10911                 RSurf_ActiveWorldEntity();
10912         else
10913                 RSurf_ActiveModelEntity(ent, false, false, false);
10914
10915         decalsystem->lastupdatetime = cl.time;
10916         decal = decalsystem->decals;
10917
10918         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10919
10920         // update vertex positions for animated models
10921         v3f = decalsystem->vertex3f;
10922         c4f = decalsystem->color4f;
10923         t2f = decalsystem->texcoord2f;
10924         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10925         {
10926                 if (!decal->color4f[0][3])
10927                         continue;
10928
10929                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10930                         continue;
10931
10932                 // skip backfaces
10933                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10934                         continue;
10935
10936                 // update color values for fading decals
10937                 if (decal->lived >= cl_decals_time.value)
10938                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10939                 else
10940                         alpha = 1.0f;
10941
10942                 c4f[ 0] = decal->color4f[0][0] * alpha;
10943                 c4f[ 1] = decal->color4f[0][1] * alpha;
10944                 c4f[ 2] = decal->color4f[0][2] * alpha;
10945                 c4f[ 3] = 1;
10946                 c4f[ 4] = decal->color4f[1][0] * alpha;
10947                 c4f[ 5] = decal->color4f[1][1] * alpha;
10948                 c4f[ 6] = decal->color4f[1][2] * alpha;
10949                 c4f[ 7] = 1;
10950                 c4f[ 8] = decal->color4f[2][0] * alpha;
10951                 c4f[ 9] = decal->color4f[2][1] * alpha;
10952                 c4f[10] = decal->color4f[2][2] * alpha;
10953                 c4f[11] = 1;
10954
10955                 t2f[0] = decal->texcoord2f[0][0];
10956                 t2f[1] = decal->texcoord2f[0][1];
10957                 t2f[2] = decal->texcoord2f[1][0];
10958                 t2f[3] = decal->texcoord2f[1][1];
10959                 t2f[4] = decal->texcoord2f[2][0];
10960                 t2f[5] = decal->texcoord2f[2][1];
10961
10962                 // update vertex positions for animated models
10963                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10964                 {
10965                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10966                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10967                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10968                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10969                 }
10970                 else
10971                 {
10972                         VectorCopy(decal->vertex3f[0], v3f);
10973                         VectorCopy(decal->vertex3f[1], v3f + 3);
10974                         VectorCopy(decal->vertex3f[2], v3f + 6);
10975                 }
10976
10977                 if (r_refdef.fogenabled)
10978                 {
10979                         alpha = RSurf_FogVertex(v3f);
10980                         VectorScale(c4f, alpha, c4f);
10981                         alpha = RSurf_FogVertex(v3f + 3);
10982                         VectorScale(c4f + 4, alpha, c4f + 4);
10983                         alpha = RSurf_FogVertex(v3f + 6);
10984                         VectorScale(c4f + 8, alpha, c4f + 8);
10985                 }
10986
10987                 v3f += 9;
10988                 c4f += 12;
10989                 t2f += 6;
10990                 numtris++;
10991         }
10992
10993         if (numtris > 0)
10994         {
10995                 r_refdef.stats.drawndecals += numtris;
10996
10997                 // now render the decals all at once
10998                 // (this assumes they all use one particle font texture!)
10999                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11000 //              R_Mesh_ResetTextureState();
11001                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11002                 GL_DepthMask(false);
11003                 GL_DepthRange(0, 1);
11004                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11005                 GL_DepthTest(true);
11006                 GL_CullFace(GL_NONE);
11007                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11008                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11009                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11010         }
11011 }
11012
11013 static void R_DrawModelDecals(void)
11014 {
11015         int i, numdecals;
11016
11017         // fade faster when there are too many decals
11018         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11019         for (i = 0;i < r_refdef.scene.numentities;i++)
11020                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11021
11022         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11023         for (i = 0;i < r_refdef.scene.numentities;i++)
11024                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11025                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11026
11027         R_DecalSystem_ApplySplatEntitiesQueue();
11028
11029         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11030         for (i = 0;i < r_refdef.scene.numentities;i++)
11031                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11032
11033         r_refdef.stats.totaldecals += numdecals;
11034
11035         if (r_showsurfaces.integer)
11036                 return;
11037
11038         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11039
11040         for (i = 0;i < r_refdef.scene.numentities;i++)
11041         {
11042                 if (!r_refdef.viewcache.entityvisible[i])
11043                         continue;
11044                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11045                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11046         }
11047 }
11048
11049 extern cvar_t mod_collision_bih;
11050 void R_DrawDebugModel(void)
11051 {
11052         entity_render_t *ent = rsurface.entity;
11053         int i, j, k, l, flagsmask;
11054         const msurface_t *surface;
11055         dp_model_t *model = ent->model;
11056         vec3_t v;
11057
11058         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11059                 return;
11060
11061         if (r_showoverdraw.value > 0)
11062         {
11063                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11064                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11065                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11066                 GL_DepthTest(false);
11067                 GL_DepthMask(false);
11068                 GL_DepthRange(0, 1);
11069                 GL_BlendFunc(GL_ONE, GL_ONE);
11070                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11071                 {
11072                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11073                                 continue;
11074                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11075                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11076                         {
11077                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11078                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11079                                 if (!rsurface.texture->currentlayers->depthmask)
11080                                         GL_Color(c, 0, 0, 1.0f);
11081                                 else if (ent == r_refdef.scene.worldentity)
11082                                         GL_Color(c, c, c, 1.0f);
11083                                 else
11084                                         GL_Color(0, c, 0, 1.0f);
11085                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11086                                 RSurf_DrawBatch();
11087                         }
11088                 }
11089                 rsurface.texture = NULL;
11090         }
11091
11092         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11093
11094 //      R_Mesh_ResetTextureState();
11095         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11096         GL_DepthRange(0, 1);
11097         GL_DepthTest(!r_showdisabledepthtest.integer);
11098         GL_DepthMask(false);
11099         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11100
11101         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11102         {
11103                 int triangleindex;
11104                 int bihleafindex;
11105                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11106                 const q3mbrush_t *brush;
11107                 const bih_t *bih = &model->collision_bih;
11108                 const bih_leaf_t *bihleaf;
11109                 float vertex3f[3][3];
11110                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11111                 cullbox = false;
11112                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11113                 {
11114                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11115                                 continue;
11116                         switch (bihleaf->type)
11117                         {
11118                         case BIH_BRUSH:
11119                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11120                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11121                                 {
11122                                         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);
11123                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11124                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11125                                 }
11126                                 break;
11127                         case BIH_COLLISIONTRIANGLE:
11128                                 triangleindex = bihleaf->itemindex;
11129                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11130                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11131                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11132                                 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);
11133                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11134                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11135                                 break;
11136                         case BIH_RENDERTRIANGLE:
11137                                 triangleindex = bihleaf->itemindex;
11138                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11139                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11140                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11141                                 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);
11142                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11143                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11144                                 break;
11145                         }
11146                 }
11147         }
11148
11149         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11150
11151         if (r_showtris.integer && qglPolygonMode)
11152         {
11153                 if (r_showdisabledepthtest.integer)
11154                 {
11155                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11156                         GL_DepthMask(false);
11157                 }
11158                 else
11159                 {
11160                         GL_BlendFunc(GL_ONE, GL_ZERO);
11161                         GL_DepthMask(true);
11162                 }
11163                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11164                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11165                 {
11166                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11167                                 continue;
11168                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11169                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11170                         {
11171                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11172                                 if (!rsurface.texture->currentlayers->depthmask)
11173                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11174                                 else if (ent == r_refdef.scene.worldentity)
11175                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11176                                 else
11177                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11178                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11179                                 RSurf_DrawBatch();
11180                         }
11181                 }
11182                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11183                 rsurface.texture = NULL;
11184         }
11185
11186         if (r_shownormals.value != 0 && qglBegin)
11187         {
11188                 if (r_showdisabledepthtest.integer)
11189                 {
11190                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11191                         GL_DepthMask(false);
11192                 }
11193                 else
11194                 {
11195                         GL_BlendFunc(GL_ONE, GL_ZERO);
11196                         GL_DepthMask(true);
11197                 }
11198                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11199                 {
11200                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11201                                 continue;
11202                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11203                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11204                         {
11205                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11206                                 qglBegin(GL_LINES);
11207                                 if (r_shownormals.value < 0)
11208                                 {
11209                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11210                                         {
11211                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11212                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11213                                                 qglVertex3f(v[0], v[1], v[2]);
11214                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11215                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11216                                                 qglVertex3f(v[0], v[1], v[2]);
11217                                         }
11218                                 }
11219                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11220                                 {
11221                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11222                                         {
11223                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11224                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11225                                                 qglVertex3f(v[0], v[1], v[2]);
11226                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11227                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11228                                                 qglVertex3f(v[0], v[1], v[2]);
11229                                         }
11230                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11231                                         {
11232                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11233                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11234                                                 qglVertex3f(v[0], v[1], v[2]);
11235                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11236                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11237                                                 qglVertex3f(v[0], v[1], v[2]);
11238                                         }
11239                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11240                                         {
11241                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11242                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11243                                                 qglVertex3f(v[0], v[1], v[2]);
11244                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11245                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11246                                                 qglVertex3f(v[0], v[1], v[2]);
11247                                         }
11248                                 }
11249                                 qglEnd();
11250                                 CHECKGLERROR
11251                         }
11252                 }
11253                 rsurface.texture = NULL;
11254         }
11255 }
11256
11257 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11258 int r_maxsurfacelist = 0;
11259 const msurface_t **r_surfacelist = NULL;
11260 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11261 {
11262         int i, j, endj, flagsmask;
11263         dp_model_t *model = r_refdef.scene.worldmodel;
11264         msurface_t *surfaces;
11265         unsigned char *update;
11266         int numsurfacelist = 0;
11267         if (model == NULL)
11268                 return;
11269
11270         if (r_maxsurfacelist < model->num_surfaces)
11271         {
11272                 r_maxsurfacelist = model->num_surfaces;
11273                 if (r_surfacelist)
11274                         Mem_Free((msurface_t**)r_surfacelist);
11275                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11276         }
11277
11278         RSurf_ActiveWorldEntity();
11279
11280         surfaces = model->data_surfaces;
11281         update = model->brushq1.lightmapupdateflags;
11282
11283         // update light styles on this submodel
11284         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11285         {
11286                 model_brush_lightstyleinfo_t *style;
11287                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11288                 {
11289                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11290                         {
11291                                 int *list = style->surfacelist;
11292                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11293                                 for (j = 0;j < style->numsurfaces;j++)
11294                                         update[list[j]] = true;
11295                         }
11296                 }
11297         }
11298
11299         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11300
11301         if (debug)
11302         {
11303                 R_DrawDebugModel();
11304                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11305                 return;
11306         }
11307
11308         rsurface.lightmaptexture = NULL;
11309         rsurface.deluxemaptexture = NULL;
11310         rsurface.uselightmaptexture = false;
11311         rsurface.texture = NULL;
11312         rsurface.rtlight = NULL;
11313         numsurfacelist = 0;
11314         // add visible surfaces to draw list
11315         for (i = 0;i < model->nummodelsurfaces;i++)
11316         {
11317                 j = model->sortedmodelsurfaces[i];
11318                 if (r_refdef.viewcache.world_surfacevisible[j])
11319                         r_surfacelist[numsurfacelist++] = surfaces + j;
11320         }
11321         // update lightmaps if needed
11322         if (model->brushq1.firstrender)
11323         {
11324                 model->brushq1.firstrender = false;
11325                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11326                         if (update[j])
11327                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11328         }
11329         else if (update)
11330         {
11331                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11332                         if (r_refdef.viewcache.world_surfacevisible[j])
11333                                 if (update[j])
11334                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11335         }
11336         // don't do anything if there were no surfaces
11337         if (!numsurfacelist)
11338         {
11339                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11340                 return;
11341         }
11342         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11343
11344         // add to stats if desired
11345         if (r_speeds.integer && !skysurfaces && !depthonly)
11346         {
11347                 r_refdef.stats.world_surfaces += numsurfacelist;
11348                 for (j = 0;j < numsurfacelist;j++)
11349                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11350         }
11351
11352         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11353 }
11354
11355 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11356 {
11357         int i, j, endj, flagsmask;
11358         dp_model_t *model = ent->model;
11359         msurface_t *surfaces;
11360         unsigned char *update;
11361         int numsurfacelist = 0;
11362         if (model == NULL)
11363                 return;
11364
11365         if (r_maxsurfacelist < model->num_surfaces)
11366         {
11367                 r_maxsurfacelist = model->num_surfaces;
11368                 if (r_surfacelist)
11369                         Mem_Free((msurface_t **)r_surfacelist);
11370                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11371         }
11372
11373         // if the model is static it doesn't matter what value we give for
11374         // wantnormals and wanttangents, so this logic uses only rules applicable
11375         // to a model, knowing that they are meaningless otherwise
11376         if (ent == r_refdef.scene.worldentity)
11377                 RSurf_ActiveWorldEntity();
11378         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11379                 RSurf_ActiveModelEntity(ent, false, false, false);
11380         else if (prepass)
11381                 RSurf_ActiveModelEntity(ent, true, true, true);
11382         else if (depthonly)
11383         {
11384                 switch (vid.renderpath)
11385                 {
11386                 case RENDERPATH_GL20:
11387                 case RENDERPATH_D3D9:
11388                 case RENDERPATH_D3D10:
11389                 case RENDERPATH_D3D11:
11390                 case RENDERPATH_SOFT:
11391                 case RENDERPATH_GLES2:
11392                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11393                         break;
11394                 case RENDERPATH_GL11:
11395                 case RENDERPATH_GL13:
11396                 case RENDERPATH_GLES1:
11397                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11398                         break;
11399                 }
11400         }
11401         else
11402         {
11403                 switch (vid.renderpath)
11404                 {
11405                 case RENDERPATH_GL20:
11406                 case RENDERPATH_D3D9:
11407                 case RENDERPATH_D3D10:
11408                 case RENDERPATH_D3D11:
11409                 case RENDERPATH_SOFT:
11410                 case RENDERPATH_GLES2:
11411                         RSurf_ActiveModelEntity(ent, true, true, false);
11412                         break;
11413                 case RENDERPATH_GL11:
11414                 case RENDERPATH_GL13:
11415                 case RENDERPATH_GLES1:
11416                         RSurf_ActiveModelEntity(ent, true, false, false);
11417                         break;
11418                 }
11419         }
11420
11421         surfaces = model->data_surfaces;
11422         update = model->brushq1.lightmapupdateflags;
11423
11424         // update light styles
11425         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11426         {
11427                 model_brush_lightstyleinfo_t *style;
11428                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11429                 {
11430                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11431                         {
11432                                 int *list = style->surfacelist;
11433                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11434                                 for (j = 0;j < style->numsurfaces;j++)
11435                                         update[list[j]] = true;
11436                         }
11437                 }
11438         }
11439
11440         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11441
11442         if (debug)
11443         {
11444                 R_DrawDebugModel();
11445                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11446                 return;
11447         }
11448
11449         rsurface.lightmaptexture = NULL;
11450         rsurface.deluxemaptexture = NULL;
11451         rsurface.uselightmaptexture = false;
11452         rsurface.texture = NULL;
11453         rsurface.rtlight = NULL;
11454         numsurfacelist = 0;
11455         // add visible surfaces to draw list
11456         for (i = 0;i < model->nummodelsurfaces;i++)
11457                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11458         // don't do anything if there were no surfaces
11459         if (!numsurfacelist)
11460         {
11461                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11462                 return;
11463         }
11464         // update lightmaps if needed
11465         if (update)
11466         {
11467                 int updated = 0;
11468                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11469                 {
11470                         if (update[j])
11471                         {
11472                                 updated++;
11473                                 R_BuildLightMap(ent, surfaces + j);
11474                         }
11475                 }
11476         }
11477         if (update)
11478                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11479                         if (update[j])
11480                                 R_BuildLightMap(ent, surfaces + j);
11481         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11482
11483         // add to stats if desired
11484         if (r_speeds.integer && !skysurfaces && !depthonly)
11485         {
11486                 r_refdef.stats.entities_surfaces += numsurfacelist;
11487                 for (j = 0;j < numsurfacelist;j++)
11488                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11489         }
11490
11491         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11492 }
11493
11494 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11495 {
11496         static texture_t texture;
11497         static msurface_t surface;
11498         const msurface_t *surfacelist = &surface;
11499
11500         // fake enough texture and surface state to render this geometry
11501
11502         texture.update_lastrenderframe = -1; // regenerate this texture
11503         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11504         texture.currentskinframe = skinframe;
11505         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11506         texture.offsetmapping = OFFSETMAPPING_OFF;
11507         texture.offsetscale = 1;
11508         texture.specularscalemod = 1;
11509         texture.specularpowermod = 1;
11510
11511         surface.texture = &texture;
11512         surface.num_triangles = numtriangles;
11513         surface.num_firsttriangle = firsttriangle;
11514         surface.num_vertices = numvertices;
11515         surface.num_firstvertex = firstvertex;
11516
11517         // now render it
11518         rsurface.texture = R_GetCurrentTexture(surface.texture);
11519         rsurface.lightmaptexture = NULL;
11520         rsurface.deluxemaptexture = NULL;
11521         rsurface.uselightmaptexture = false;
11522         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11523 }
11524
11525 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)
11526 {
11527         static msurface_t surface;
11528         const msurface_t *surfacelist = &surface;
11529
11530         // fake enough texture and surface state to render this geometry
11531         surface.texture = texture;
11532         surface.num_triangles = numtriangles;
11533         surface.num_firsttriangle = firsttriangle;
11534         surface.num_vertices = numvertices;
11535         surface.num_firstvertex = firstvertex;
11536
11537         // now render it
11538         rsurface.texture = R_GetCurrentTexture(surface.texture);
11539         rsurface.lightmaptexture = NULL;
11540         rsurface.deluxemaptexture = NULL;
11541         rsurface.uselightmaptexture = false;
11542         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11543 }