]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix water renders with r_viewscale
[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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
99
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
103
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
126
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
135
136 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)"};
137 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"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 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"};
144 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"};
145 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
146 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
147 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"};
148 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)"};
149 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)"};
150 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
151
152 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)"};
153 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
154 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)"};
155 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
156 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)"};
157 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)"};
158 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
159 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
160 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)"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168
169 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)"};
170 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
171 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"};
172 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
173 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
174 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
175
176 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
177 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
178 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
179 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
180
181 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
182 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
183 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
184 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
185 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
186 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
187 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
188
189 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
190 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
191 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
192 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)"};
193 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
194 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
195 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
196 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
198 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
199
200 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"};
201
202 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"};
203
204 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
205
206 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
207 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"};
208 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
209 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
210 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
211 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
212 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)"};
213 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
214 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
218
219 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
220
221 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
222
223 extern cvar_t v_glslgamma;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL11:
1853         case RENDERPATH_GL13:
1854         case RENDERPATH_GLES1:
1855                 break;
1856         case RENDERPATH_SOFT:
1857                 break;
1858         }
1859 }
1860
1861 void R_GLSL_DumpShader_f(void)
1862 {
1863         int i;
1864         qfile_t *file;
1865
1866         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, glslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("glsl/default.glsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to glsl/default.glsl\n");
1882
1883         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinhlslshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("hlsl/default.hlsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1899 }
1900
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1902 {
1903         if (!second)
1904                 texturemode = GL_MODULATE;
1905         switch (vid.renderpath)
1906         {
1907         case RENDERPATH_D3D9:
1908 #ifdef SUPPORTD3D
1909                 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))));
1910                 R_Mesh_TexBind(GL20TU_FIRST , first );
1911                 R_Mesh_TexBind(GL20TU_SECOND, second);
1912 #endif
1913                 break;
1914         case RENDERPATH_D3D10:
1915                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1916                 break;
1917         case RENDERPATH_D3D11:
1918                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_GL20:
1921         case RENDERPATH_GLES2:
1922                 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))));
1923                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1924                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1925                 break;
1926         case RENDERPATH_GL13:
1927         case RENDERPATH_GLES1:
1928                 R_Mesh_TexBind(0, first );
1929                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1930                 R_Mesh_TexBind(1, second);
1931                 if (second)
1932                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1933                 break;
1934         case RENDERPATH_GL11:
1935                 R_Mesh_TexBind(0, first );
1936                 break;
1937         case RENDERPATH_SOFT:
1938                 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))));
1939                 R_Mesh_TexBind(GL20TU_FIRST , first );
1940                 R_Mesh_TexBind(GL20TU_SECOND, second);
1941                 break;
1942         }
1943 }
1944
1945 void R_SetupShader_DepthOrShadow(void)
1946 {
1947         switch (vid.renderpath)
1948         {
1949         case RENDERPATH_D3D9:
1950 #ifdef SUPPORTD3D
1951                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1963                 break;
1964         case RENDERPATH_GL13:
1965         case RENDERPATH_GLES1:
1966                 R_Mesh_TexBind(0, 0);
1967                 R_Mesh_TexBind(1, 0);
1968                 break;
1969         case RENDERPATH_GL11:
1970                 R_Mesh_TexBind(0, 0);
1971                 break;
1972         case RENDERPATH_SOFT:
1973                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1974                 break;
1975         }
1976 }
1977
1978 void R_SetupShader_ShowDepth(void)
1979 {
1980         switch (vid.renderpath)
1981         {
1982         case RENDERPATH_D3D9:
1983 #ifdef SUPPORTHLSL
1984                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1985 #endif
1986                 break;
1987         case RENDERPATH_D3D10:
1988                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_D3D11:
1991                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992                 break;
1993         case RENDERPATH_GL20:
1994         case RENDERPATH_GLES2:
1995                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1996                 break;
1997         case RENDERPATH_GL13:
1998         case RENDERPATH_GLES1:
1999                 break;
2000         case RENDERPATH_GL11:
2001                 break;
2002         case RENDERPATH_SOFT:
2003                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2004                 break;
2005         }
2006 }
2007
2008 extern qboolean r_shadow_usingdeferredprepass;
2009 extern cvar_t r_shadow_deferred_8bitrange;
2010 extern rtexture_t *r_shadow_attenuationgradienttexture;
2011 extern rtexture_t *r_shadow_attenuation2dtexture;
2012 extern rtexture_t *r_shadow_attenuation3dtexture;
2013 extern qboolean r_shadow_usingshadowmap2d;
2014 extern qboolean r_shadow_usingshadowmaportho;
2015 extern float r_shadow_shadowmap_texturescale[2];
2016 extern float r_shadow_shadowmap_parameters[4];
2017 extern qboolean r_shadow_shadowmapvsdct;
2018 extern qboolean r_shadow_shadowmapsampler;
2019 extern int r_shadow_shadowmappcf;
2020 extern rtexture_t *r_shadow_shadowmap2dtexture;
2021 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2022 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2023 extern matrix4x4_t r_shadow_shadowmapmatrix;
2024 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2025 extern int r_shadow_prepass_width;
2026 extern int r_shadow_prepass_height;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2028 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2030 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2031 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2032
2033 #define BLENDFUNC_ALLOWS_COLORMOD      1
2034 #define BLENDFUNC_ALLOWS_FOG           2
2035 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2036 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2037 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2038 static int R_BlendFuncFlags(int src, int dst)
2039 {
2040         int r = 0;
2041
2042         // a blendfunc allows colormod if:
2043         // a) it can never keep the destination pixel invariant, or
2044         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2045         // this is to prevent unintended side effects from colormod
2046
2047         // a blendfunc allows fog if:
2048         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2049         // this is to prevent unintended side effects from fog
2050
2051         // these checks are the output of fogeval.pl
2052
2053         r |= BLENDFUNC_ALLOWS_COLORMOD;
2054         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2055         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2056         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2058         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2063         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2064         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2075
2076         return r;
2077 }
2078
2079 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)
2080 {
2081         // select a permutation of the lighting shader appropriate to this
2082         // combination of texture, entity, light source, and fogging, only use the
2083         // minimum features necessary to avoid wasting rendering time in the
2084         // fragment shader on features that are not being used
2085         unsigned int permutation = 0;
2086         unsigned int mode = 0;
2087         int blendfuncflags;
2088         static float dummy_colormod[3] = {1, 1, 1};
2089         float *colormod = rsurface.colormod;
2090         float m16f[16];
2091         matrix4x4_t tempmatrix;
2092         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2093         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2094                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2095         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2096                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2097         if (rsurfacepass == RSURFPASS_BACKGROUND)
2098         {
2099                 // distorted background
2100                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2101                 {
2102                         mode = SHADERMODE_WATER;
2103                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2104                         {
2105                                 // this is the right thing to do for wateralpha
2106                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2107                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2108                         }
2109                         else
2110                         {
2111                                 // this is the right thing to do for entity alpha
2112                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2113                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114                         }
2115                 }
2116                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2117                 {
2118                         mode = SHADERMODE_REFRACTION;
2119                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                 }
2122                 else
2123                 {
2124                         mode = SHADERMODE_GENERIC;
2125                         permutation |= SHADERPERMUTATION_DIFFUSE;
2126                         GL_BlendFunc(GL_ONE, GL_ZERO);
2127                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2128                 }
2129         }
2130         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2131         {
2132                 if (r_glsl_offsetmapping.integer)
2133                 {
2134                         switch(rsurface.texture->offsetmapping)
2135                         {
2136                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2137                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139                         case OFFSETMAPPING_OFF: break;
2140                         }
2141                 }
2142                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144                 // normalmap (deferred prepass), may use alpha test on diffuse
2145                 mode = SHADERMODE_DEFERREDGEOMETRY;
2146                 GL_BlendFunc(GL_ONE, GL_ZERO);
2147                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2148         }
2149         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2150         {
2151                 if (r_glsl_offsetmapping.integer)
2152                 {
2153                         switch(rsurface.texture->offsetmapping)
2154                         {
2155                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158                         case OFFSETMAPPING_OFF: break;
2159                         }
2160                 }
2161                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2163                 // light source
2164                 mode = SHADERMODE_LIGHTSOURCE;
2165                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2167                 if (diffusescale > 0)
2168                         permutation |= SHADERPERMUTATION_DIFFUSE;
2169                 if (specularscale > 0)
2170                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171                 if (r_refdef.fogenabled)
2172                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173                 if (rsurface.texture->colormapping)
2174                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2175                 if (r_shadow_usingshadowmap2d)
2176                 {
2177                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178                         if(r_shadow_shadowmapvsdct)
2179                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2180
2181                         if (r_shadow_shadowmapsampler)
2182                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183                         if (r_shadow_shadowmappcf > 1)
2184                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185                         else if (r_shadow_shadowmappcf)
2186                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2187                 }
2188                 if (rsurface.texture->reflectmasktexture)
2189                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2192         }
2193         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // unshaded geometry (fullbright or ambient model lighting)
2208                 mode = SHADERMODE_FLATCOLOR;
2209                 ambientscale = diffusescale = specularscale = 0;
2210                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2211                         permutation |= SHADERPERMUTATION_GLOW;
2212                 if (r_refdef.fogenabled)
2213                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2214                 if (rsurface.texture->colormapping)
2215                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2216                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2217                 {
2218                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2219                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2220
2221                         if (r_shadow_shadowmapsampler)
2222                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2223                         if (r_shadow_shadowmappcf > 1)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2225                         else if (r_shadow_shadowmappcf)
2226                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2227                 }
2228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2229                         permutation |= SHADERPERMUTATION_REFLECTION;
2230                 if (rsurface.texture->reflectmasktexture)
2231                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2232                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234         }
2235         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2236         {
2237                 if (r_glsl_offsetmapping.integer)
2238                 {
2239                         switch(rsurface.texture->offsetmapping)
2240                         {
2241                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2242                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244                         case OFFSETMAPPING_OFF: break;
2245                         }
2246                 }
2247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2248                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2249                 // directional model lighting
2250                 mode = SHADERMODE_LIGHTDIRECTION;
2251                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252                         permutation |= SHADERPERMUTATION_GLOW;
2253                 permutation |= SHADERPERMUTATION_DIFFUSE;
2254                 if (specularscale > 0)
2255                         permutation |= SHADERPERMUTATION_SPECULAR;
2256                 if (r_refdef.fogenabled)
2257                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2258                 if (rsurface.texture->colormapping)
2259                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2260                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2261                 {
2262                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2263                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2264
2265                         if (r_shadow_shadowmapsampler)
2266                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2267                         if (r_shadow_shadowmappcf > 1)
2268                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2269                         else if (r_shadow_shadowmappcf)
2270                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2271                 }
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2273                         permutation |= SHADERPERMUTATION_REFLECTION;
2274                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2275                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2276                 if (rsurface.texture->reflectmasktexture)
2277                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278                 if (r_shadow_bouncegridtexture)
2279                 {
2280                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2281                         if (r_shadow_bouncegriddirectional)
2282                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2283                 }
2284                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286         }
2287         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2288         {
2289                 if (r_glsl_offsetmapping.integer)
2290                 {
2291                         switch(rsurface.texture->offsetmapping)
2292                         {
2293                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_OFF: break;
2297                         }
2298                 }
2299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301                 // ambient model lighting
2302                 mode = SHADERMODE_LIGHTDIRECTION;
2303                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304                         permutation |= SHADERPERMUTATION_GLOW;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313
2314                         if (r_shadow_shadowmapsampler)
2315                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316                         if (r_shadow_shadowmappcf > 1)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318                         else if (r_shadow_shadowmappcf)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322                         permutation |= SHADERPERMUTATION_REFLECTION;
2323                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325                 if (rsurface.texture->reflectmasktexture)
2326                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327                 if (r_shadow_bouncegridtexture)
2328                 {
2329                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330                         if (r_shadow_bouncegriddirectional)
2331                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2332                 }
2333                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335         }
2336         else
2337         {
2338                 if (r_glsl_offsetmapping.integer)
2339                 {
2340                         switch(rsurface.texture->offsetmapping)
2341                         {
2342                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_OFF: break;
2346                         }
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350                 // lightmapped wall
2351                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352                         permutation |= SHADERPERMUTATION_GLOW;
2353                 if (r_refdef.fogenabled)
2354                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355                 if (rsurface.texture->colormapping)
2356                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2357                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2358                 {
2359                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2361
2362                         if (r_shadow_shadowmapsampler)
2363                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2364                         if (r_shadow_shadowmappcf > 1)
2365                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2366                         else if (r_shadow_shadowmappcf)
2367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2368                 }
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370                         permutation |= SHADERPERMUTATION_REFLECTION;
2371                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2372                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2373                 if (rsurface.texture->reflectmasktexture)
2374                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2375                 if (FAKELIGHT_ENABLED)
2376                 {
2377                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2378                         mode = SHADERMODE_FAKELIGHT;
2379                         permutation |= SHADERPERMUTATION_DIFFUSE;
2380                         if (specularscale > 0)
2381                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2382                 }
2383                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2384                 {
2385                         // deluxemapping (light direction texture)
2386                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2387                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2388                         else
2389                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390                         permutation |= SHADERPERMUTATION_DIFFUSE;
2391                         if (specularscale > 0)
2392                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2393                 }
2394                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2395                 {
2396                         // fake deluxemapping (uniform light direction in tangentspace)
2397                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398                         permutation |= SHADERPERMUTATION_DIFFUSE;
2399                         if (specularscale > 0)
2400                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2401                 }
2402                 else if (rsurface.uselightmaptexture)
2403                 {
2404                         // ordinary lightmapping (q1bsp, q3bsp)
2405                         mode = SHADERMODE_LIGHTMAP;
2406                 }
2407                 else
2408                 {
2409                         // ordinary vertex coloring (q3bsp)
2410                         mode = SHADERMODE_VERTEXCOLOR;
2411                 }
2412                 if (r_shadow_bouncegridtexture)
2413                 {
2414                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2415                         if (r_shadow_bouncegriddirectional)
2416                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2417                 }
2418                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420         }
2421         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2422                 colormod = dummy_colormod;
2423         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2424                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2425         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2426                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2427         switch(vid.renderpath)
2428         {
2429         case RENDERPATH_D3D9:
2430 #ifdef SUPPORTD3D
2431                 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);
2432                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2433                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2434                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2435                 if (mode == SHADERMODE_LIGHTSOURCE)
2436                 {
2437                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2438                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2439                 }
2440                 else
2441                 {
2442                         if (mode == SHADERMODE_LIGHTDIRECTION)
2443                         {
2444                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2445                         }
2446                 }
2447                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2449                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2450                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2451                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2452
2453                 if (mode == SHADERMODE_LIGHTSOURCE)
2454                 {
2455                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2456                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2460
2461                         // additive passes are only darkened by fog, not tinted
2462                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2463                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2464                 }
2465                 else
2466                 {
2467                         if (mode == SHADERMODE_FLATCOLOR)
2468                         {
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2470                         }
2471                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2472                         {
2473                                 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]);
2474                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2475                                 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);
2476                                 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);
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2480                         }
2481                         else
2482                         {
2483                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2485                                 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);
2486                                 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);
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2488                         }
2489                         // additive passes are only darkened by fog, not tinted
2490                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2491                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2492                         else
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2494                         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);
2495                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2502                         if (mode == SHADERMODE_WATER)
2503                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2504                 }
2505                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2506                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2507                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2508                 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));
2509                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2510                 if (rsurface.texture->pantstexture)
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2512                 else
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2514                 if (rsurface.texture->shirttexture)
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2516                 else
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2518                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2519                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2522                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2523                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2524                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2527                         );
2528                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2529                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2530
2531                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2532                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2533                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2534                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2535                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2536                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2538                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2539                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2540                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2541                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2542                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2543                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2544                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2545                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2546                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2547                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2548                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2549                 {
2550                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2551                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2552                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2553                 }
2554                 else
2555                 {
2556                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2557                 }
2558 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2559 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2560                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2561                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2562                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2563                 {
2564                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2565                         if (rsurface.rtlight)
2566                         {
2567                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2568                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2569                         }
2570                 }
2571 #endif
2572                 break;
2573         case RENDERPATH_D3D10:
2574                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2575                 break;
2576         case RENDERPATH_D3D11:
2577                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2578                 break;
2579         case RENDERPATH_GL20:
2580         case RENDERPATH_GLES2:
2581                 if (!vid.useinterleavedarrays)
2582                 {
2583                         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);
2584                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2585                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2586                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2591                 }
2592                 else
2593                 {
2594                         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);
2595                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2596                 }
2597                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2598                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2599                 if (mode == SHADERMODE_LIGHTSOURCE)
2600                 {
2601                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2602                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2603                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2604                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2605                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2606                         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);
2607         
2608                         // additive passes are only darkened by fog, not tinted
2609                         if (r_glsl_permutation->loc_FogColor >= 0)
2610                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2611                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612                 }
2613                 else
2614                 {
2615                         if (mode == SHADERMODE_FLATCOLOR)
2616                         {
2617                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2618                         }
2619                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2620                         {
2621                                 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]);
2622                                 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]);
2623                                 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);
2624                                 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);
2625                                 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);
2626                                 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]);
2627                                 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]);
2628                         }
2629                         else
2630                         {
2631                                 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]);
2632                                 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]);
2633                                 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);
2634                                 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);
2635                                 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);
2636                         }
2637                         // additive passes are only darkened by fog, not tinted
2638                         if (r_glsl_permutation->loc_FogColor >= 0)
2639                         {
2640                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2641                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2642                                 else
2643                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2644                         }
2645                         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);
2646                         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]);
2647                         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]);
2648                         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]);
2649                         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]);
2650                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2651                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2652                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2653                         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]);
2654                 }
2655                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2656                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2657                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2658                 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]);
2659                 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]);
2660
2661                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2662                 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));
2663                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2664                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2665                 {
2666                         if (rsurface.texture->pantstexture)
2667                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2668                         else
2669                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2670                 }
2671                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2672                 {
2673                         if (rsurface.texture->shirttexture)
2674                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2675                         else
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2677                 }
2678                 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]);
2679                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2681                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2682                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2683                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2687                         );
2688                 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]);
2689                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2690                 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);}
2691                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2692
2693                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2694                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2695                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2696                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2697                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2698                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2699                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2700                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2701                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2704                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2705                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2706                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2707                 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);
2708                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2709                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2710                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2711                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2712                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2713                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2714                 {
2715                         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);
2716                         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);
2717                         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);
2718                 }
2719                 else
2720                 {
2721                         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);
2722                 }
2723                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2724                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2725                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2726                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2727                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2728                 {
2729                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2730                         if (rsurface.rtlight)
2731                         {
2732                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2733                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2734                         }
2735                 }
2736                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2737                 CHECKGLERROR
2738                 break;
2739         case RENDERPATH_GL11:
2740         case RENDERPATH_GL13:
2741         case RENDERPATH_GLES1:
2742                 break;
2743         case RENDERPATH_SOFT:
2744                 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);
2745                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2746                 R_SetupShader_SetPermutationSoft(mode, permutation);
2747                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2748                 if (mode == SHADERMODE_LIGHTSOURCE)
2749                 {
2750                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2751                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2756         
2757                         // additive passes are only darkened by fog, not tinted
2758                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2759                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2760                 }
2761                 else
2762                 {
2763                         if (mode == SHADERMODE_FLATCOLOR)
2764                         {
2765                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2766                         }
2767                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2768                         {
2769                                 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]);
2770                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2771                                 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);
2772                                 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);
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2774                                 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]);
2775                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2776                         }
2777                         else
2778                         {
2779                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2781                                 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);
2782                                 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);
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2784                         }
2785                         // additive passes are only darkened by fog, not tinted
2786                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2787                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2788                         else
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2790                         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);
2791                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2793                         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]);
2794                         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]);
2795                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2798                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2799                 }
2800                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2803                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2804                 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]);
2805
2806                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2807                 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));
2808                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2809                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2810                 {
2811                         if (rsurface.texture->pantstexture)
2812                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2813                         else
2814                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2815                 }
2816                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2817                 {
2818                         if (rsurface.texture->shirttexture)
2819                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2820                         else
2821                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2822                 }
2823                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2824                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2827                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2828                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2829                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2830                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2832                         );
2833                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2834                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2835
2836                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2837                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2838                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2839                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2840                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2841                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2844                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2845                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2846                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2847                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2848                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2849                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2850                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2851                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2852                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2853                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2854                 {
2855                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2856                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2857                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2858                 }
2859                 else
2860                 {
2861                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2862                 }
2863 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2864 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2865                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2866                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2867                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2868                 {
2869                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2870                         if (rsurface.rtlight)
2871                         {
2872                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2873                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2874                         }
2875                 }
2876                 break;
2877         }
2878 }
2879
2880 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2881 {
2882         // select a permutation of the lighting shader appropriate to this
2883         // combination of texture, entity, light source, and fogging, only use the
2884         // minimum features necessary to avoid wasting rendering time in the
2885         // fragment shader on features that are not being used
2886         unsigned int permutation = 0;
2887         unsigned int mode = 0;
2888         const float *lightcolorbase = rtlight->currentcolor;
2889         float ambientscale = rtlight->ambientscale;
2890         float diffusescale = rtlight->diffusescale;
2891         float specularscale = rtlight->specularscale;
2892         // this is the location of the light in view space
2893         vec3_t viewlightorigin;
2894         // this transforms from view space (camera) to light space (cubemap)
2895         matrix4x4_t viewtolight;
2896         matrix4x4_t lighttoview;
2897         float viewtolight16f[16];
2898         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2899         // light source
2900         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2901         if (rtlight->currentcubemap != r_texture_whitecube)
2902                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2903         if (diffusescale > 0)
2904                 permutation |= SHADERPERMUTATION_DIFFUSE;
2905         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2906                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2907         if (r_shadow_usingshadowmap2d)
2908         {
2909                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2910                 if (r_shadow_shadowmapvsdct)
2911                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2912
2913                 if (r_shadow_shadowmapsampler)
2914                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2915                 if (r_shadow_shadowmappcf > 1)
2916                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2917                 else if (r_shadow_shadowmappcf)
2918                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2919         }
2920         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2921         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2922         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2923         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2924         switch(vid.renderpath)
2925         {
2926         case RENDERPATH_D3D9:
2927 #ifdef SUPPORTD3D
2928                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2929                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2930                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2932                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2934                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2935                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2936                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2937                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2938                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2939
2940                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2941                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2942                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2943                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2944                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2945                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2946 #endif
2947                 break;
2948         case RENDERPATH_D3D10:
2949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950                 break;
2951         case RENDERPATH_D3D11:
2952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953                 break;
2954         case RENDERPATH_GL20:
2955         case RENDERPATH_GLES2:
2956                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2957                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2958                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2959                 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);
2960                 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);
2961                 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);
2962                 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]);
2963                 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]);
2964                 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));
2965                 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]);
2966                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2967
2968                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2969                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2970                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2971                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2972                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2973                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2974                 break;
2975         case RENDERPATH_GL11:
2976         case RENDERPATH_GL13:
2977         case RENDERPATH_GLES1:
2978                 break;
2979         case RENDERPATH_SOFT:
2980                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2981                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2982                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2983                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2986                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2987                 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]);
2988                 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));
2989                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2990                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2991
2992                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2993                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2994                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2995                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2996                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2997                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2998                 break;
2999         }
3000 }
3001
3002 #define SKINFRAME_HASH 1024
3003
3004 typedef struct
3005 {
3006         int loadsequence; // incremented each level change
3007         memexpandablearray_t array;
3008         skinframe_t *hash[SKINFRAME_HASH];
3009 }
3010 r_skinframe_t;
3011 r_skinframe_t r_skinframe;
3012
3013 void R_SkinFrame_PrepareForPurge(void)
3014 {
3015         r_skinframe.loadsequence++;
3016         // wrap it without hitting zero
3017         if (r_skinframe.loadsequence >= 200)
3018                 r_skinframe.loadsequence = 1;
3019 }
3020
3021 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3022 {
3023         if (!skinframe)
3024                 return;
3025         // mark the skinframe as used for the purging code
3026         skinframe->loadsequence = r_skinframe.loadsequence;
3027 }
3028
3029 void R_SkinFrame_Purge(void)
3030 {
3031         int i;
3032         skinframe_t *s;
3033         for (i = 0;i < SKINFRAME_HASH;i++)
3034         {
3035                 for (s = r_skinframe.hash[i];s;s = s->next)
3036                 {
3037                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3038                         {
3039                                 if (s->merged == s->base)
3040                                         s->merged = NULL;
3041                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3042                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3043                                 R_PurgeTexture(s->merged);s->merged = NULL;
3044                                 R_PurgeTexture(s->base  );s->base   = NULL;
3045                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3046                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3047                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3048                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3049                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3050                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3051                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3052                                 s->loadsequence = 0;
3053                         }
3054                 }
3055         }
3056 }
3057
3058 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3059         skinframe_t *item;
3060         char basename[MAX_QPATH];
3061
3062         Image_StripImageExtension(name, basename, sizeof(basename));
3063
3064         if( last == NULL ) {
3065                 int hashindex;
3066                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3067                 item = r_skinframe.hash[hashindex];
3068         } else {
3069                 item = last->next;
3070         }
3071
3072         // linearly search through the hash bucket
3073         for( ; item ; item = item->next ) {
3074                 if( !strcmp( item->basename, basename ) ) {
3075                         return item;
3076                 }
3077         }
3078         return NULL;
3079 }
3080
3081 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3082 {
3083         skinframe_t *item;
3084         int hashindex;
3085         char basename[MAX_QPATH];
3086
3087         Image_StripImageExtension(name, basename, sizeof(basename));
3088
3089         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3090         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3091                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3092                         break;
3093
3094         if (!item) {
3095                 rtexture_t *dyntexture;
3096                 // check whether its a dynamic texture
3097                 dyntexture = CL_GetDynTexture( basename );
3098                 if (!add && !dyntexture)
3099                         return NULL;
3100                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3101                 memset(item, 0, sizeof(*item));
3102                 strlcpy(item->basename, basename, sizeof(item->basename));
3103                 item->base = dyntexture; // either NULL or dyntexture handle
3104                 item->textureflags = textureflags;
3105                 item->comparewidth = comparewidth;
3106                 item->compareheight = compareheight;
3107                 item->comparecrc = comparecrc;
3108                 item->next = r_skinframe.hash[hashindex];
3109                 r_skinframe.hash[hashindex] = item;
3110         }
3111         else if( item->base == NULL )
3112         {
3113                 rtexture_t *dyntexture;
3114                 // check whether its a dynamic texture
3115                 // 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]
3116                 dyntexture = CL_GetDynTexture( basename );
3117                 item->base = dyntexture; // either NULL or dyntexture handle
3118         }
3119
3120         R_SkinFrame_MarkUsed(item);
3121         return item;
3122 }
3123
3124 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3125         { \
3126                 unsigned long long avgcolor[5], wsum; \
3127                 int pix, comp, w; \
3128                 avgcolor[0] = 0; \
3129                 avgcolor[1] = 0; \
3130                 avgcolor[2] = 0; \
3131                 avgcolor[3] = 0; \
3132                 avgcolor[4] = 0; \
3133                 wsum = 0; \
3134                 for(pix = 0; pix < cnt; ++pix) \
3135                 { \
3136                         w = 0; \
3137                         for(comp = 0; comp < 3; ++comp) \
3138                                 w += getpixel; \
3139                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3140                         { \
3141                                 ++wsum; \
3142                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3143                                 w = getpixel; \
3144                                 for(comp = 0; comp < 3; ++comp) \
3145                                         avgcolor[comp] += getpixel * w; \
3146                                 avgcolor[3] += w; \
3147                         } \
3148                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3149                         avgcolor[4] += getpixel; \
3150                 } \
3151                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3152                         avgcolor[3] = 1; \
3153                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3154                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3157         }
3158
3159 extern cvar_t gl_picmip;
3160 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3161 {
3162         int j;
3163         unsigned char *pixels;
3164         unsigned char *bumppixels;
3165         unsigned char *basepixels = NULL;
3166         int basepixels_width = 0;
3167         int basepixels_height = 0;
3168         skinframe_t *skinframe;
3169         rtexture_t *ddsbase = NULL;
3170         qboolean ddshasalpha = false;
3171         float ddsavgcolor[4];
3172         char basename[MAX_QPATH];
3173         int miplevel = R_PicmipForFlags(textureflags);
3174         int savemiplevel = miplevel;
3175         int mymiplevel;
3176
3177         if (cls.state == ca_dedicated)
3178                 return NULL;
3179
3180         // return an existing skinframe if already loaded
3181         // if loading of the first image fails, don't make a new skinframe as it
3182         // would cause all future lookups of this to be missing
3183         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3184         if (skinframe && skinframe->base)
3185                 return skinframe;
3186
3187         Image_StripImageExtension(name, basename, sizeof(basename));
3188
3189         // check for DDS texture file first
3190         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3191         {
3192                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3193                 if (basepixels == NULL)
3194                         return NULL;
3195         }
3196
3197         // FIXME handle miplevel
3198
3199         if (developer_loading.integer)
3200                 Con_Printf("loading skin \"%s\"\n", name);
3201
3202         // we've got some pixels to store, so really allocate this new texture now
3203         if (!skinframe)
3204                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3205         skinframe->stain = NULL;
3206         skinframe->merged = NULL;
3207         skinframe->base = NULL;
3208         skinframe->pants = NULL;
3209         skinframe->shirt = NULL;
3210         skinframe->nmap = NULL;
3211         skinframe->gloss = NULL;
3212         skinframe->glow = NULL;
3213         skinframe->fog = NULL;
3214         skinframe->reflect = NULL;
3215         skinframe->hasalpha = false;
3216
3217         if (ddsbase)
3218         {
3219                 skinframe->base = ddsbase;
3220                 skinframe->hasalpha = ddshasalpha;
3221                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3222                 if (r_loadfog && skinframe->hasalpha)
3223                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3224                 //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]);
3225         }
3226         else
3227         {
3228                 basepixels_width = image_width;
3229                 basepixels_height = image_height;
3230                 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);
3231                 if (textureflags & TEXF_ALPHA)
3232                 {
3233                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3234                         {
3235                                 if (basepixels[j] < 255)
3236                                 {
3237                                         skinframe->hasalpha = true;
3238                                         break;
3239                                 }
3240                         }
3241                         if (r_loadfog && skinframe->hasalpha)
3242                         {
3243                                 // has transparent pixels
3244                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3245                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3246                                 {
3247                                         pixels[j+0] = 255;
3248                                         pixels[j+1] = 255;
3249                                         pixels[j+2] = 255;
3250                                         pixels[j+3] = basepixels[j+3];
3251                                 }
3252                                 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);
3253                                 Mem_Free(pixels);
3254                         }
3255                 }
3256                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3257                 //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]);
3258                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3259                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3260                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3261                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3262         }
3263
3264         if (r_loaddds)
3265         {
3266                 mymiplevel = savemiplevel;
3267                 if (r_loadnormalmap)
3268                         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);
3269                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270                 if (r_loadgloss)
3271                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275         }
3276
3277         // _norm is the name used by tenebrae and has been adopted as standard
3278         if (r_loadnormalmap && skinframe->nmap == NULL)
3279         {
3280                 mymiplevel = savemiplevel;
3281                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3282                 {
3283                         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);
3284                         Mem_Free(pixels);
3285                         pixels = NULL;
3286                 }
3287                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3288                 {
3289                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3290                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3291                         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);
3292                         Mem_Free(pixels);
3293                         Mem_Free(bumppixels);
3294                 }
3295                 else if (r_shadow_bumpscale_basetexture.value > 0)
3296                 {
3297                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3298                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3299                         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);
3300                         Mem_Free(pixels);
3301                 }
3302                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3303                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3304         }
3305
3306         // _luma is supported only for tenebrae compatibility
3307         // _glow is the preferred name
3308         mymiplevel = savemiplevel;
3309         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))))
3310         {
3311                 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);
3312                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3313                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3314                 Mem_Free(pixels);pixels = NULL;
3315         }
3316
3317         mymiplevel = savemiplevel;
3318         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3319         {
3320                 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);
3321                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3322                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3323                 Mem_Free(pixels);
3324                 pixels = NULL;
3325         }
3326
3327         mymiplevel = savemiplevel;
3328         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3329         {
3330                 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);
3331                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3332                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3333                 Mem_Free(pixels);
3334                 pixels = NULL;
3335         }
3336
3337         mymiplevel = savemiplevel;
3338         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3339         {
3340                 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);
3341                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3342                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3343                 Mem_Free(pixels);
3344                 pixels = NULL;
3345         }
3346
3347         mymiplevel = savemiplevel;
3348         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3349         {
3350                 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);
3351                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3352                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3353                 Mem_Free(pixels);
3354                 pixels = NULL;
3355         }
3356
3357         if (basepixels)
3358                 Mem_Free(basepixels);
3359
3360         return skinframe;
3361 }
3362
3363 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3364 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3365 {
3366         int i;
3367         unsigned char *temp1, *temp2;
3368         skinframe_t *skinframe;
3369
3370         if (cls.state == ca_dedicated)
3371                 return NULL;
3372
3373         // if already loaded just return it, otherwise make a new skinframe
3374         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3375         if (skinframe && skinframe->base)
3376                 return skinframe;
3377
3378         skinframe->stain = NULL;
3379         skinframe->merged = NULL;
3380         skinframe->base = NULL;
3381         skinframe->pants = NULL;
3382         skinframe->shirt = NULL;
3383         skinframe->nmap = NULL;
3384         skinframe->gloss = NULL;
3385         skinframe->glow = NULL;
3386         skinframe->fog = NULL;
3387         skinframe->reflect = NULL;
3388         skinframe->hasalpha = false;
3389
3390         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3391         if (!skindata)
3392                 return NULL;
3393
3394         if (developer_loading.integer)
3395                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3396
3397         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3398         {
3399                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3400                 temp2 = temp1 + width * height * 4;
3401                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3402                 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);
3403                 Mem_Free(temp1);
3404         }
3405         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3406         if (textureflags & TEXF_ALPHA)
3407         {
3408                 for (i = 3;i < width * height * 4;i += 4)
3409                 {
3410                         if (skindata[i] < 255)
3411                         {
3412                                 skinframe->hasalpha = true;
3413                                 break;
3414                         }
3415                 }
3416                 if (r_loadfog && skinframe->hasalpha)
3417                 {
3418                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3419                         memcpy(fogpixels, skindata, width * height * 4);
3420                         for (i = 0;i < width * height * 4;i += 4)
3421                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3422                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3423                         Mem_Free(fogpixels);
3424                 }
3425         }
3426
3427         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3428         //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]);
3429
3430         return skinframe;
3431 }
3432
3433 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3434 {
3435         int i;
3436         int featuresmask;
3437         skinframe_t *skinframe;
3438
3439         if (cls.state == ca_dedicated)
3440                 return NULL;
3441
3442         // if already loaded just return it, otherwise make a new skinframe
3443         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3444         if (skinframe && skinframe->base)
3445                 return skinframe;
3446
3447         skinframe->stain = NULL;
3448         skinframe->merged = NULL;
3449         skinframe->base = NULL;
3450         skinframe->pants = NULL;
3451         skinframe->shirt = NULL;
3452         skinframe->nmap = NULL;
3453         skinframe->gloss = NULL;
3454         skinframe->glow = NULL;
3455         skinframe->fog = NULL;
3456         skinframe->reflect = NULL;
3457         skinframe->hasalpha = false;
3458
3459         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3460         if (!skindata)
3461                 return NULL;
3462
3463         if (developer_loading.integer)
3464                 Con_Printf("loading quake skin \"%s\"\n", name);
3465
3466         // 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)
3467         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3468         memcpy(skinframe->qpixels, skindata, width*height);
3469         skinframe->qwidth = width;
3470         skinframe->qheight = height;
3471
3472         featuresmask = 0;
3473         for (i = 0;i < width * height;i++)
3474                 featuresmask |= palette_featureflags[skindata[i]];
3475
3476         skinframe->hasalpha = false;
3477         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3478         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3479         skinframe->qgeneratemerged = true;
3480         skinframe->qgeneratebase = skinframe->qhascolormapping;
3481         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3482
3483         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3484         //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]);
3485
3486         return skinframe;
3487 }
3488
3489 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3490 {
3491         int width;
3492         int height;
3493         unsigned char *skindata;
3494
3495         if (!skinframe->qpixels)
3496                 return;
3497
3498         if (!skinframe->qhascolormapping)
3499                 colormapped = false;
3500
3501         if (colormapped)
3502         {
3503                 if (!skinframe->qgeneratebase)
3504                         return;
3505         }
3506         else
3507         {
3508                 if (!skinframe->qgeneratemerged)
3509                         return;
3510         }
3511
3512         width = skinframe->qwidth;
3513         height = skinframe->qheight;
3514         skindata = skinframe->qpixels;
3515
3516         if (skinframe->qgeneratenmap)
3517         {
3518                 unsigned char *temp1, *temp2;
3519                 skinframe->qgeneratenmap = false;
3520                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3521                 temp2 = temp1 + width * height * 4;
3522                 // use either a custom palette or the quake palette
3523                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3524                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3525                 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);
3526                 Mem_Free(temp1);
3527         }
3528
3529         if (skinframe->qgenerateglow)
3530         {
3531                 skinframe->qgenerateglow = false;
3532                 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
3533         }
3534
3535         if (colormapped)
3536         {
3537                 skinframe->qgeneratebase = false;
3538                 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);
3539                 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);
3540                 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);
3541         }
3542         else
3543         {
3544                 skinframe->qgeneratemerged = false;
3545                 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);
3546         }
3547
3548         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3549         {
3550                 Mem_Free(skinframe->qpixels);
3551                 skinframe->qpixels = NULL;
3552         }
3553 }
3554
3555 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)
3556 {
3557         int i;
3558         skinframe_t *skinframe;
3559
3560         if (cls.state == ca_dedicated)
3561                 return NULL;
3562
3563         // if already loaded just return it, otherwise make a new skinframe
3564         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3565         if (skinframe && skinframe->base)
3566                 return skinframe;
3567
3568         skinframe->stain = NULL;
3569         skinframe->merged = NULL;
3570         skinframe->base = NULL;
3571         skinframe->pants = NULL;
3572         skinframe->shirt = NULL;
3573         skinframe->nmap = NULL;
3574         skinframe->gloss = NULL;
3575         skinframe->glow = NULL;
3576         skinframe->fog = NULL;
3577         skinframe->reflect = NULL;
3578         skinframe->hasalpha = false;
3579
3580         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3581         if (!skindata)
3582                 return NULL;
3583
3584         if (developer_loading.integer)
3585                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3586
3587         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3588         if (textureflags & TEXF_ALPHA)
3589         {
3590                 for (i = 0;i < width * height;i++)
3591                 {
3592                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3593                         {
3594                                 skinframe->hasalpha = true;
3595                                 break;
3596                         }
3597                 }
3598                 if (r_loadfog && skinframe->hasalpha)
3599                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3600         }
3601
3602         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3603         //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]);
3604
3605         return skinframe;
3606 }
3607
3608 skinframe_t *R_SkinFrame_LoadMissing(void)
3609 {
3610         skinframe_t *skinframe;
3611
3612         if (cls.state == ca_dedicated)
3613                 return NULL;
3614
3615         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3616         skinframe->stain = NULL;
3617         skinframe->merged = NULL;
3618         skinframe->base = NULL;
3619         skinframe->pants = NULL;
3620         skinframe->shirt = NULL;
3621         skinframe->nmap = NULL;
3622         skinframe->gloss = NULL;
3623         skinframe->glow = NULL;
3624         skinframe->fog = NULL;
3625         skinframe->reflect = NULL;
3626         skinframe->hasalpha = false;
3627
3628         skinframe->avgcolor[0] = rand() / RAND_MAX;
3629         skinframe->avgcolor[1] = rand() / RAND_MAX;
3630         skinframe->avgcolor[2] = rand() / RAND_MAX;
3631         skinframe->avgcolor[3] = 1;
3632
3633         return skinframe;
3634 }
3635
3636 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3637 typedef struct suffixinfo_s
3638 {
3639         const char *suffix;
3640         qboolean flipx, flipy, flipdiagonal;
3641 }
3642 suffixinfo_t;
3643 static suffixinfo_t suffix[3][6] =
3644 {
3645         {
3646                 {"px",   false, false, false},
3647                 {"nx",   false, false, false},
3648                 {"py",   false, false, false},
3649                 {"ny",   false, false, false},
3650                 {"pz",   false, false, false},
3651                 {"nz",   false, false, false}
3652         },
3653         {
3654                 {"posx", false, false, false},
3655                 {"negx", false, false, false},
3656                 {"posy", false, false, false},
3657                 {"negy", false, false, false},
3658                 {"posz", false, false, false},
3659                 {"negz", false, false, false}
3660         },
3661         {
3662                 {"rt",    true, false,  true},
3663                 {"lf",   false,  true,  true},
3664                 {"ft",    true,  true, false},
3665                 {"bk",   false, false, false},
3666                 {"up",    true, false,  true},
3667                 {"dn",    true, false,  true}
3668         }
3669 };
3670
3671 static int componentorder[4] = {0, 1, 2, 3};
3672
3673 rtexture_t *R_LoadCubemap(const char *basename)
3674 {
3675         int i, j, cubemapsize;
3676         unsigned char *cubemappixels, *image_buffer;
3677         rtexture_t *cubemaptexture;
3678         char name[256];
3679         // must start 0 so the first loadimagepixels has no requested width/height
3680         cubemapsize = 0;
3681         cubemappixels = NULL;
3682         cubemaptexture = NULL;
3683         // keep trying different suffix groups (posx, px, rt) until one loads
3684         for (j = 0;j < 3 && !cubemappixels;j++)
3685         {
3686                 // load the 6 images in the suffix group
3687                 for (i = 0;i < 6;i++)
3688                 {
3689                         // generate an image name based on the base and and suffix
3690                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3691                         // load it
3692                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3693                         {
3694                                 // an image loaded, make sure width and height are equal
3695                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3696                                 {
3697                                         // if this is the first image to load successfully, allocate the cubemap memory
3698                                         if (!cubemappixels && image_width >= 1)
3699                                         {
3700                                                 cubemapsize = image_width;
3701                                                 // note this clears to black, so unavailable sides are black
3702                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3703                                         }
3704                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3705                                         if (cubemappixels)
3706                                                 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);
3707                                 }
3708                                 else
3709                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3710                                 // free the image
3711                                 Mem_Free(image_buffer);
3712                         }
3713                 }
3714         }
3715         // if a cubemap loaded, upload it
3716         if (cubemappixels)
3717         {
3718                 if (developer_loading.integer)
3719                         Con_Printf("loading cubemap \"%s\"\n", basename);
3720
3721                 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);
3722                 Mem_Free(cubemappixels);
3723         }
3724         else
3725         {
3726                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3727                 if (developer_loading.integer)
3728                 {
3729                         Con_Printf("(tried tried images ");
3730                         for (j = 0;j < 3;j++)
3731                                 for (i = 0;i < 6;i++)
3732                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3733                         Con_Print(" and was unable to find any of them).\n");
3734                 }
3735         }
3736         return cubemaptexture;
3737 }
3738
3739 rtexture_t *R_GetCubemap(const char *basename)
3740 {
3741         int i;
3742         for (i = 0;i < r_texture_numcubemaps;i++)
3743                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3744                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3745         if (i >= MAX_CUBEMAPS)
3746                 return r_texture_whitecube;
3747         r_texture_numcubemaps++;
3748         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3749         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3750         return r_texture_cubemaps[i].texture;
3751 }
3752
3753 void R_FreeCubemaps(void)
3754 {
3755         int i;
3756         for (i = 0;i < r_texture_numcubemaps;i++)
3757         {
3758                 if (developer_loading.integer)
3759                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3760                 if (r_texture_cubemaps[i].texture)
3761                         R_FreeTexture(r_texture_cubemaps[i].texture);
3762         }
3763         r_texture_numcubemaps = 0;
3764 }
3765
3766 void R_Main_FreeViewCache(void)
3767 {
3768         if (r_refdef.viewcache.entityvisible)
3769                 Mem_Free(r_refdef.viewcache.entityvisible);
3770         if (r_refdef.viewcache.world_pvsbits)
3771                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3772         if (r_refdef.viewcache.world_leafvisible)
3773                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3774         if (r_refdef.viewcache.world_surfacevisible)
3775                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3776         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3777 }
3778
3779 void R_Main_ResizeViewCache(void)
3780 {
3781         int numentities = r_refdef.scene.numentities;
3782         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3783         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3784         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3785         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3786         if (r_refdef.viewcache.maxentities < numentities)
3787         {
3788                 r_refdef.viewcache.maxentities = numentities;
3789                 if (r_refdef.viewcache.entityvisible)
3790                         Mem_Free(r_refdef.viewcache.entityvisible);
3791                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3792         }
3793         if (r_refdef.viewcache.world_numclusters != numclusters)
3794         {
3795                 r_refdef.viewcache.world_numclusters = numclusters;
3796                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3797                 if (r_refdef.viewcache.world_pvsbits)
3798                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3799                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3800         }
3801         if (r_refdef.viewcache.world_numleafs != numleafs)
3802         {
3803                 r_refdef.viewcache.world_numleafs = numleafs;
3804                 if (r_refdef.viewcache.world_leafvisible)
3805                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3806                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3807         }
3808         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3809         {
3810                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3811                 if (r_refdef.viewcache.world_surfacevisible)
3812                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3813                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3814         }
3815 }
3816
3817 extern rtexture_t *loadingscreentexture;
3818 void gl_main_start(void)
3819 {
3820         loadingscreentexture = NULL;
3821         r_texture_blanknormalmap = NULL;
3822         r_texture_white = NULL;
3823         r_texture_grey128 = NULL;
3824         r_texture_black = NULL;
3825         r_texture_whitecube = NULL;
3826         r_texture_normalizationcube = NULL;
3827         r_texture_fogattenuation = NULL;
3828         r_texture_fogheighttexture = NULL;
3829         r_texture_gammaramps = NULL;
3830         r_texture_numcubemaps = 0;
3831
3832         r_loaddds = r_texture_dds_load.integer != 0;
3833         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3834
3835         switch(vid.renderpath)
3836         {
3837         case RENDERPATH_GL20:
3838         case RENDERPATH_D3D9:
3839         case RENDERPATH_D3D10:
3840         case RENDERPATH_D3D11:
3841         case RENDERPATH_SOFT:
3842         case RENDERPATH_GLES2:
3843                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3844                 Cvar_SetValueQuick(&gl_combine, 1);
3845                 Cvar_SetValueQuick(&r_glsl, 1);
3846                 r_loadnormalmap = true;
3847                 r_loadgloss = true;
3848                 r_loadfog = false;
3849                 break;
3850         case RENDERPATH_GL13:
3851         case RENDERPATH_GLES1:
3852                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3853                 Cvar_SetValueQuick(&gl_combine, 1);
3854                 Cvar_SetValueQuick(&r_glsl, 0);
3855                 r_loadnormalmap = false;
3856                 r_loadgloss = false;
3857                 r_loadfog = true;
3858                 break;
3859         case RENDERPATH_GL11:
3860                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861                 Cvar_SetValueQuick(&gl_combine, 0);
3862                 Cvar_SetValueQuick(&r_glsl, 0);
3863                 r_loadnormalmap = false;
3864                 r_loadgloss = false;
3865                 r_loadfog = true;
3866                 break;
3867         }
3868
3869         R_AnimCache_Free();
3870         R_FrameData_Reset();
3871
3872         r_numqueries = 0;
3873         r_maxqueries = 0;
3874         memset(r_queries, 0, sizeof(r_queries));
3875
3876         r_qwskincache = NULL;
3877         r_qwskincache_size = 0;
3878
3879         // due to caching of texture_t references, the collision cache must be reset
3880         Collision_Cache_Reset(true);
3881
3882         // set up r_skinframe loading system for textures
3883         memset(&r_skinframe, 0, sizeof(r_skinframe));
3884         r_skinframe.loadsequence = 1;
3885         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3886
3887         r_main_texturepool = R_AllocTexturePool();
3888         R_BuildBlankTextures();
3889         R_BuildNoTexture();
3890         if (vid.support.arb_texture_cube_map)
3891         {
3892                 R_BuildWhiteCube();
3893                 R_BuildNormalizationCube();
3894         }
3895         r_texture_fogattenuation = NULL;
3896         r_texture_fogheighttexture = NULL;
3897         r_texture_gammaramps = NULL;
3898         //r_texture_fogintensity = NULL;
3899         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3900         memset(&r_waterstate, 0, sizeof(r_waterstate));
3901         r_glsl_permutation = NULL;
3902         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3903         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3904         glslshaderstring = NULL;
3905 #ifdef SUPPORTD3D
3906         r_hlsl_permutation = NULL;
3907         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3908         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3909 #endif
3910         hlslshaderstring = NULL;
3911         memset(&r_svbsp, 0, sizeof (r_svbsp));
3912
3913         r_refdef.fogmasktable_density = 0;
3914 }
3915
3916 void gl_main_shutdown(void)
3917 {
3918         R_AnimCache_Free();
3919         R_FrameData_Reset();
3920
3921         R_Main_FreeViewCache();
3922
3923         switch(vid.renderpath)
3924         {
3925         case RENDERPATH_GL11:
3926         case RENDERPATH_GL13:
3927         case RENDERPATH_GL20:
3928         case RENDERPATH_GLES1:
3929         case RENDERPATH_GLES2:
3930                 if (r_maxqueries)
3931                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3932                 break;
3933         case RENDERPATH_D3D9:
3934                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935                 break;
3936         case RENDERPATH_D3D10:
3937                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3938                 break;
3939         case RENDERPATH_D3D11:
3940                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3941                 break;
3942         case RENDERPATH_SOFT:
3943                 break;
3944         }
3945
3946         r_numqueries = 0;
3947         r_maxqueries = 0;
3948         memset(r_queries, 0, sizeof(r_queries));
3949
3950         r_qwskincache = NULL;
3951         r_qwskincache_size = 0;
3952
3953         // clear out the r_skinframe state
3954         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3955         memset(&r_skinframe, 0, sizeof(r_skinframe));
3956
3957         if (r_svbsp.nodes)
3958                 Mem_Free(r_svbsp.nodes);
3959         memset(&r_svbsp, 0, sizeof (r_svbsp));
3960         R_FreeTexturePool(&r_main_texturepool);
3961         loadingscreentexture = NULL;
3962         r_texture_blanknormalmap = NULL;
3963         r_texture_white = NULL;
3964         r_texture_grey128 = NULL;
3965         r_texture_black = NULL;
3966         r_texture_whitecube = NULL;
3967         r_texture_normalizationcube = NULL;
3968         r_texture_fogattenuation = NULL;
3969         r_texture_fogheighttexture = NULL;
3970         r_texture_gammaramps = NULL;
3971         r_texture_numcubemaps = 0;
3972         //r_texture_fogintensity = NULL;
3973         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3974         memset(&r_waterstate, 0, sizeof(r_waterstate));
3975         R_GLSL_Restart_f();
3976
3977         r_glsl_permutation = NULL;
3978         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3979         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3980         glslshaderstring = NULL;
3981 #ifdef SUPPORTD3D
3982         r_hlsl_permutation = NULL;
3983         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3984         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3985 #endif
3986         hlslshaderstring = NULL;
3987 }
3988
3989 extern void CL_ParseEntityLump(char *entitystring);
3990 void gl_main_newmap(void)
3991 {
3992         // FIXME: move this code to client
3993         char *entities, entname[MAX_QPATH];
3994         if (r_qwskincache)
3995                 Mem_Free(r_qwskincache);
3996         r_qwskincache = NULL;
3997         r_qwskincache_size = 0;
3998         if (cl.worldmodel)
3999         {
4000                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4001                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4002                 {
4003                         CL_ParseEntityLump(entities);
4004                         Mem_Free(entities);
4005                         return;
4006                 }
4007                 if (cl.worldmodel->brush.entities)
4008                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4009         }
4010         R_Main_FreeViewCache();
4011
4012         R_FrameData_Reset();
4013 }
4014
4015 void GL_Main_Init(void)
4016 {
4017         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4018
4019         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4020         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4021         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4022         if (gamemode == GAME_NEHAHRA)
4023         {
4024                 Cvar_RegisterVariable (&gl_fogenable);
4025                 Cvar_RegisterVariable (&gl_fogdensity);
4026                 Cvar_RegisterVariable (&gl_fogred);
4027                 Cvar_RegisterVariable (&gl_foggreen);
4028                 Cvar_RegisterVariable (&gl_fogblue);
4029                 Cvar_RegisterVariable (&gl_fogstart);
4030                 Cvar_RegisterVariable (&gl_fogend);
4031                 Cvar_RegisterVariable (&gl_skyclip);
4032         }
4033         Cvar_RegisterVariable(&r_motionblur);
4034         Cvar_RegisterVariable(&r_motionblur_maxblur);
4035         Cvar_RegisterVariable(&r_motionblur_bmin);
4036         Cvar_RegisterVariable(&r_motionblur_vmin);
4037         Cvar_RegisterVariable(&r_motionblur_vmax);
4038         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4039         Cvar_RegisterVariable(&r_motionblur_randomize);
4040         Cvar_RegisterVariable(&r_damageblur);
4041         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4042         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4043         Cvar_RegisterVariable(&r_equalize_entities_by);
4044         Cvar_RegisterVariable(&r_equalize_entities_to);
4045         Cvar_RegisterVariable(&r_depthfirst);
4046         Cvar_RegisterVariable(&r_useinfinitefarclip);
4047         Cvar_RegisterVariable(&r_farclip_base);
4048         Cvar_RegisterVariable(&r_farclip_world);
4049         Cvar_RegisterVariable(&r_nearclip);
4050         Cvar_RegisterVariable(&r_deformvertexes);
4051         Cvar_RegisterVariable(&r_transparent);
4052         Cvar_RegisterVariable(&r_showoverdraw);
4053         Cvar_RegisterVariable(&r_showbboxes);
4054         Cvar_RegisterVariable(&r_showsurfaces);
4055         Cvar_RegisterVariable(&r_showtris);
4056         Cvar_RegisterVariable(&r_shownormals);
4057         Cvar_RegisterVariable(&r_showlighting);
4058         Cvar_RegisterVariable(&r_showshadowvolumes);
4059         Cvar_RegisterVariable(&r_showcollisionbrushes);
4060         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4061         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4062         Cvar_RegisterVariable(&r_showdisabledepthtest);
4063         Cvar_RegisterVariable(&r_drawportals);
4064         Cvar_RegisterVariable(&r_drawentities);
4065         Cvar_RegisterVariable(&r_draw2d);
4066         Cvar_RegisterVariable(&r_drawworld);
4067         Cvar_RegisterVariable(&r_cullentities_trace);
4068         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4069         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4070         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4071         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4072         Cvar_RegisterVariable(&r_drawviewmodel);
4073         Cvar_RegisterVariable(&r_drawexteriormodel);
4074         Cvar_RegisterVariable(&r_speeds);
4075         Cvar_RegisterVariable(&r_fullbrights);
4076         Cvar_RegisterVariable(&r_wateralpha);
4077         Cvar_RegisterVariable(&r_dynamic);
4078         Cvar_RegisterVariable(&r_fakelight);
4079         Cvar_RegisterVariable(&r_fakelight_intensity);
4080         Cvar_RegisterVariable(&r_fullbright);
4081         Cvar_RegisterVariable(&r_shadows);
4082         Cvar_RegisterVariable(&r_shadows_darken);
4083         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4084         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4085         Cvar_RegisterVariable(&r_shadows_throwdistance);
4086         Cvar_RegisterVariable(&r_shadows_throwdirection);
4087         Cvar_RegisterVariable(&r_shadows_focus);
4088         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4089         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4090         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4091         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4092         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4093         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4094         Cvar_RegisterVariable(&r_fog_exp2);
4095         Cvar_RegisterVariable(&r_fog_clear);
4096         Cvar_RegisterVariable(&r_drawfog);
4097         Cvar_RegisterVariable(&r_transparentdepthmasking);
4098         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4099         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4100         Cvar_RegisterVariable(&r_texture_dds_load);
4101         Cvar_RegisterVariable(&r_texture_dds_save);
4102         Cvar_RegisterVariable(&r_textureunits);
4103         Cvar_RegisterVariable(&gl_combine);
4104         Cvar_RegisterVariable(&r_viewfbo);
4105         Cvar_RegisterVariable(&r_viewscale);
4106         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4107         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4108         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4109         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4110         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4111         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4112         Cvar_RegisterVariable(&r_glsl);
4113         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4114         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4115         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4116         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4117         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4118         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4119         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4120         Cvar_RegisterVariable(&r_glsl_postprocess);
4121         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4122         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4123         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4124         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4125         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4127         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4129
4130         Cvar_RegisterVariable(&r_water);
4131         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4132         Cvar_RegisterVariable(&r_water_clippingplanebias);
4133         Cvar_RegisterVariable(&r_water_refractdistort);
4134         Cvar_RegisterVariable(&r_water_reflectdistort);
4135         Cvar_RegisterVariable(&r_water_scissormode);
4136         Cvar_RegisterVariable(&r_lerpsprites);
4137         Cvar_RegisterVariable(&r_lerpmodels);
4138         Cvar_RegisterVariable(&r_lerplightstyles);
4139         Cvar_RegisterVariable(&r_waterscroll);
4140         Cvar_RegisterVariable(&r_bloom);
4141         Cvar_RegisterVariable(&r_bloom_colorscale);
4142         Cvar_RegisterVariable(&r_bloom_brighten);
4143         Cvar_RegisterVariable(&r_bloom_blur);
4144         Cvar_RegisterVariable(&r_bloom_resolution);
4145         Cvar_RegisterVariable(&r_bloom_colorexponent);
4146         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4147         Cvar_RegisterVariable(&r_hdr);
4148         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4149         Cvar_RegisterVariable(&r_hdr_glowintensity);
4150         Cvar_RegisterVariable(&r_hdr_range);
4151         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4152         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4153         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4154         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4155         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4156         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4157         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4158         Cvar_RegisterVariable(&developer_texturelogging);
4159         Cvar_RegisterVariable(&gl_lightmaps);
4160         Cvar_RegisterVariable(&r_test);
4161         Cvar_RegisterVariable(&r_glsl_saturation);
4162         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4163         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4164         Cvar_RegisterVariable(&r_framedatasize);
4165         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4166                 Cvar_SetValue("r_fullbrights", 0);
4167         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4168
4169         Cvar_RegisterVariable(&r_track_sprites);
4170         Cvar_RegisterVariable(&r_track_sprites_flags);
4171         Cvar_RegisterVariable(&r_track_sprites_scalew);
4172         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4173         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4174         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4175         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4176         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4177 }
4178
4179 extern void R_Textures_Init(void);
4180 extern void GL_Draw_Init(void);
4181 extern void GL_Main_Init(void);
4182 extern void R_Shadow_Init(void);
4183 extern void R_Sky_Init(void);
4184 extern void GL_Surf_Init(void);
4185 extern void R_Particles_Init(void);
4186 extern void R_Explosion_Init(void);
4187 extern void gl_backend_init(void);
4188 extern void Sbar_Init(void);
4189 extern void R_LightningBeams_Init(void);
4190 extern void Mod_RenderInit(void);
4191 extern void Font_Init(void);
4192
4193 void Render_Init(void)
4194 {
4195         gl_backend_init();
4196         R_Textures_Init();
4197         GL_Main_Init();
4198         Font_Init();
4199         GL_Draw_Init();
4200         R_Shadow_Init();
4201         R_Sky_Init();
4202         GL_Surf_Init();
4203         Sbar_Init();
4204         R_Particles_Init();
4205         R_Explosion_Init();
4206         R_LightningBeams_Init();
4207         Mod_RenderInit();
4208 }
4209
4210 /*
4211 ===============
4212 GL_Init
4213 ===============
4214 */
4215 extern char *ENGINE_EXTENSIONS;
4216 void GL_Init (void)
4217 {
4218         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4219         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4220         gl_version = (const char *)qglGetString(GL_VERSION);
4221         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4222
4223         if (!gl_extensions)
4224                 gl_extensions = "";
4225         if (!gl_platformextensions)
4226                 gl_platformextensions = "";
4227
4228         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4229         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4230         Con_Printf("GL_VERSION: %s\n", gl_version);
4231         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4232         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4233
4234         VID_CheckExtensions();
4235
4236         // LordHavoc: report supported extensions
4237         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4238
4239         // clear to black (loading plaque will be seen over this)
4240         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4241 }
4242
4243 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4244 {
4245         int i;
4246         mplane_t *p;
4247         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4248         {
4249                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4250                 if (i == 4)
4251                         continue;
4252                 p = r_refdef.view.frustum + i;
4253                 switch(p->signbits)
4254                 {
4255                 default:
4256                 case 0:
4257                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4258                                 return true;
4259                         break;
4260                 case 1:
4261                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4262                                 return true;
4263                         break;
4264                 case 2:
4265                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4266                                 return true;
4267                         break;
4268                 case 3:
4269                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4270                                 return true;
4271                         break;
4272                 case 4:
4273                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4274                                 return true;
4275                         break;
4276                 case 5:
4277                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4278                                 return true;
4279                         break;
4280                 case 6:
4281                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4282                                 return true;
4283                         break;
4284                 case 7:
4285                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4286                                 return true;
4287                         break;
4288                 }
4289         }
4290         return false;
4291 }
4292
4293 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4294 {
4295         int i;
4296         const mplane_t *p;
4297         for (i = 0;i < numplanes;i++)
4298         {
4299                 p = planes + i;
4300                 switch(p->signbits)
4301                 {
4302                 default:
4303                 case 0:
4304                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4305                                 return true;
4306                         break;
4307                 case 1:
4308                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4309                                 return true;
4310                         break;
4311                 case 2:
4312                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 case 3:
4316                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4317                                 return true;
4318                         break;
4319                 case 4:
4320                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4321                                 return true;
4322                         break;
4323                 case 5:
4324                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4325                                 return true;
4326                         break;
4327                 case 6:
4328                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4329                                 return true;
4330                         break;
4331                 case 7:
4332                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4333                                 return true;
4334                         break;
4335                 }
4336         }
4337         return false;
4338 }
4339
4340 //==================================================================================
4341
4342 // LordHavoc: this stores temporary data used within the same frame
4343
4344 typedef struct r_framedata_mem_s
4345 {
4346         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4347         size_t size; // how much usable space
4348         size_t current; // how much space in use
4349         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4350         size_t wantedsize; // how much space was allocated
4351         unsigned char *data; // start of real data (16byte aligned)
4352 }
4353 r_framedata_mem_t;
4354
4355 static r_framedata_mem_t *r_framedata_mem;
4356
4357 void R_FrameData_Reset(void)
4358 {
4359         while (r_framedata_mem)
4360         {
4361                 r_framedata_mem_t *next = r_framedata_mem->purge;
4362                 Mem_Free(r_framedata_mem);
4363                 r_framedata_mem = next;
4364         }
4365 }
4366
4367 void R_FrameData_Resize(void)
4368 {
4369         size_t wantedsize;
4370         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4371         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4372         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4373         {
4374                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4375                 newmem->wantedsize = wantedsize;
4376                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4377                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4378                 newmem->current = 0;
4379                 newmem->mark = 0;
4380                 newmem->purge = r_framedata_mem;
4381                 r_framedata_mem = newmem;
4382         }
4383 }
4384
4385 void R_FrameData_NewFrame(void)
4386 {
4387         R_FrameData_Resize();
4388         if (!r_framedata_mem)
4389                 return;
4390         // if we ran out of space on the last frame, free the old memory now
4391         while (r_framedata_mem->purge)
4392         {
4393                 // repeatedly remove the second item in the list, leaving only head
4394                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4395                 Mem_Free(r_framedata_mem->purge);
4396                 r_framedata_mem->purge = next;
4397         }
4398         // reset the current mem pointer
4399         r_framedata_mem->current = 0;
4400         r_framedata_mem->mark = 0;
4401 }
4402
4403 void *R_FrameData_Alloc(size_t size)
4404 {
4405         void *data;
4406
4407         // align to 16 byte boundary - the data pointer is already aligned, so we
4408         // only need to ensure the size of every allocation is also aligned
4409         size = (size + 15) & ~15;
4410
4411         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4412         {
4413                 // emergency - we ran out of space, allocate more memory
4414                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4415                 R_FrameData_Resize();
4416         }
4417
4418         data = r_framedata_mem->data + r_framedata_mem->current;
4419         r_framedata_mem->current += size;
4420
4421         // count the usage for stats
4422         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4423         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4424
4425         return (void *)data;
4426 }
4427
4428 void *R_FrameData_Store(size_t size, void *data)
4429 {
4430         void *d = R_FrameData_Alloc(size);
4431         if (d && data)
4432                 memcpy(d, data, size);
4433         return d;
4434 }
4435
4436 void R_FrameData_SetMark(void)
4437 {
4438         if (!r_framedata_mem)
4439                 return;
4440         r_framedata_mem->mark = r_framedata_mem->current;
4441 }
4442
4443 void R_FrameData_ReturnToMark(void)
4444 {
4445         if (!r_framedata_mem)
4446                 return;
4447         r_framedata_mem->current = r_framedata_mem->mark;
4448 }
4449
4450 //==================================================================================
4451
4452 // LordHavoc: animcache originally written by Echon, rewritten since then
4453
4454 /**
4455  * Animation cache prevents re-generating mesh data for an animated model
4456  * multiple times in one frame for lighting, shadowing, reflections, etc.
4457  */
4458
4459 void R_AnimCache_Free(void)
4460 {
4461 }
4462
4463 void R_AnimCache_ClearCache(void)
4464 {
4465         int i;
4466         entity_render_t *ent;
4467
4468         for (i = 0;i < r_refdef.scene.numentities;i++)
4469         {
4470                 ent = r_refdef.scene.entities[i];
4471                 ent->animcache_vertex3f = NULL;
4472                 ent->animcache_normal3f = NULL;
4473                 ent->animcache_svector3f = NULL;
4474                 ent->animcache_tvector3f = NULL;
4475                 ent->animcache_vertexmesh = NULL;
4476                 ent->animcache_vertex3fbuffer = NULL;
4477                 ent->animcache_vertexmeshbuffer = NULL;
4478         }
4479 }
4480
4481 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4482 {
4483         int i;
4484
4485         // check if we need the meshbuffers
4486         if (!vid.useinterleavedarrays)
4487                 return;
4488
4489         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4490                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4491         // TODO: upload vertex3f buffer?
4492         if (ent->animcache_vertexmesh)
4493         {
4494                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4495                 for (i = 0;i < numvertices;i++)
4496                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4497                 if (ent->animcache_svector3f)
4498                         for (i = 0;i < numvertices;i++)
4499                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4500                 if (ent->animcache_tvector3f)
4501                         for (i = 0;i < numvertices;i++)
4502                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4503                 if (ent->animcache_normal3f)
4504                         for (i = 0;i < numvertices;i++)
4505                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4506                 // TODO: upload vertexmeshbuffer?
4507         }
4508 }
4509
4510 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4511 {
4512         dp_model_t *model = ent->model;
4513         int numvertices;
4514         // see if it's already cached this frame
4515         if (ent->animcache_vertex3f)
4516         {
4517                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4518                 if (wantnormals || wanttangents)
4519                 {
4520                         if (ent->animcache_normal3f)
4521                                 wantnormals = false;
4522                         if (ent->animcache_svector3f)
4523                                 wanttangents = false;
4524                         if (wantnormals || wanttangents)
4525                         {
4526                                 numvertices = model->surfmesh.num_vertices;
4527                                 if (wantnormals)
4528                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4529                                 if (wanttangents)
4530                                 {
4531                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4532                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533                                 }
4534                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4535                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4536                         }
4537                 }
4538         }
4539         else
4540         {
4541                 // see if this ent is worth caching
4542                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4543                         return false;
4544                 // get some memory for this entity and generate mesh data
4545                 numvertices = model->surfmesh.num_vertices;
4546                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547                 if (wantnormals)
4548                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549                 if (wanttangents)
4550                 {
4551                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4552                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4553                 }
4554                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4555                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4556         }
4557         return true;
4558 }
4559
4560 void R_AnimCache_CacheVisibleEntities(void)
4561 {
4562         int i;
4563         qboolean wantnormals = true;
4564         qboolean wanttangents = !r_showsurfaces.integer;
4565
4566         switch(vid.renderpath)
4567         {
4568         case RENDERPATH_GL20:
4569         case RENDERPATH_D3D9:
4570         case RENDERPATH_D3D10:
4571         case RENDERPATH_D3D11:
4572         case RENDERPATH_GLES2:
4573                 break;
4574         case RENDERPATH_GL11:
4575         case RENDERPATH_GL13:
4576         case RENDERPATH_GLES1:
4577                 wanttangents = false;
4578                 break;
4579         case RENDERPATH_SOFT:
4580                 break;
4581         }
4582
4583         if (r_shownormals.integer)
4584                 wanttangents = wantnormals = true;
4585
4586         // TODO: thread this
4587         // NOTE: R_PrepareRTLights() also caches entities
4588
4589         for (i = 0;i < r_refdef.scene.numentities;i++)
4590                 if (r_refdef.viewcache.entityvisible[i])
4591                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4592 }
4593
4594 //==================================================================================
4595
4596 static void R_View_UpdateEntityLighting (void)
4597 {
4598         int i;
4599         entity_render_t *ent;
4600         vec3_t tempdiffusenormal, avg;
4601         vec_t f, fa, fd, fdd;
4602         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605         {
4606                 ent = r_refdef.scene.entities[i];
4607
4608                 // skip unseen models
4609                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4610                         continue;
4611
4612                 // skip bsp models
4613                 if (ent->model && ent->model->brush.num_leafs)
4614                 {
4615                         // TODO: use modellight for r_ambient settings on world?
4616                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4617                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4618                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4619                         continue;
4620                 }
4621
4622                 // fetch the lighting from the worldmodel data
4623                 VectorClear(ent->modellight_ambient);
4624                 VectorClear(ent->modellight_diffuse);
4625                 VectorClear(tempdiffusenormal);
4626                 if (ent->flags & RENDER_LIGHT)
4627                 {
4628                         vec3_t org;
4629                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4630
4631                         // complete lightning for lit sprites
4632                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4633                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4634                         {
4635                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4636                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4637                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4638                         }
4639                         else
4640                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4641
4642                         if(ent->flags & RENDER_EQUALIZE)
4643                         {
4644                                 // first fix up ambient lighting...
4645                                 if(r_equalize_entities_minambient.value > 0)
4646                                 {
4647                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4648                                         if(fd > 0)
4649                                         {
4650                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4651                                                 if(fa < r_equalize_entities_minambient.value * fd)
4652                                                 {
4653                                                         // solve:
4654                                                         //   fa'/fd' = minambient
4655                                                         //   fa'+0.25*fd' = fa+0.25*fd
4656                                                         //   ...
4657                                                         //   fa' = fd' * minambient
4658                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4659                                                         //   ...
4660                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4661                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4662                                                         //   ...
4663                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4664                                                         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
4665                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4666                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4667                                                 }
4668                                         }
4669                                 }
4670
4671                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4672                                 {
4673                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4674                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4675                                         f = fa + 0.25 * fd;
4676                                         if(f > 0)
4677                                         {
4678                                                 // adjust brightness and saturation to target
4679                                                 avg[0] = avg[1] = avg[2] = fa / f;
4680                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4681                                                 avg[0] = avg[1] = avg[2] = fd / f;
4682                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4683                                         }
4684                                 }
4685                         }
4686                 }
4687                 else // highly rare
4688                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4689
4690                 // move the light direction into modelspace coordinates for lighting code
4691                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4692                 if(VectorLength2(ent->modellight_lightdir) == 0)
4693                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4694                 VectorNormalize(ent->modellight_lightdir);
4695         }
4696 }
4697
4698 #define MAX_LINEOFSIGHTTRACES 64
4699
4700 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4701 {
4702         int i;
4703         vec3_t boxmins, boxmaxs;
4704         vec3_t start;
4705         vec3_t end;
4706         dp_model_t *model = r_refdef.scene.worldmodel;
4707
4708         if (!model || !model->brush.TraceLineOfSight)
4709                 return true;
4710
4711         // expand the box a little
4712         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4713         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4714         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4715         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4716         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4717         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4718
4719         // return true if eye is inside enlarged box
4720         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4721                 return true;
4722
4723         // try center
4724         VectorCopy(eye, start);
4725         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4726         if (model->brush.TraceLineOfSight(model, start, end))
4727                 return true;
4728
4729         // try various random positions
4730         for (i = 0;i < numsamples;i++)
4731         {
4732                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4733                 if (model->brush.TraceLineOfSight(model, start, end))
4734                         return true;
4735         }
4736
4737         return false;
4738 }
4739
4740
4741 static void R_View_UpdateEntityVisible (void)
4742 {
4743         int i;
4744         int renderimask;
4745         int samples;
4746         entity_render_t *ent;
4747
4748         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4749                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4750                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4751                 :                                                          RENDER_EXTERIORMODEL;
4752         if (!r_drawviewmodel.integer)
4753                 renderimask |= RENDER_VIEWMODEL;
4754         if (!r_drawexteriormodel.integer)
4755                 renderimask |= RENDER_EXTERIORMODEL;
4756         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4757         {
4758                 // worldmodel can check visibility
4759                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4760                 for (i = 0;i < r_refdef.scene.numentities;i++)
4761                 {
4762                         ent = r_refdef.scene.entities[i];
4763                         if (!(ent->flags & renderimask))
4764                         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)))
4765                         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))
4766                                 r_refdef.viewcache.entityvisible[i] = true;
4767                 }
4768         }
4769         else
4770         {
4771                 // no worldmodel or it can't check visibility
4772                 for (i = 0;i < r_refdef.scene.numentities;i++)
4773                 {
4774                         ent = r_refdef.scene.entities[i];
4775                         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));
4776                 }
4777         }
4778         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4779                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4780         {
4781                 for (i = 0;i < r_refdef.scene.numentities;i++)
4782                 {
4783                         if (!r_refdef.viewcache.entityvisible[i])
4784                                 continue;
4785                         ent = r_refdef.scene.entities[i];
4786                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4787                         {
4788                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4789                                 if (samples < 0)
4790                                         continue; // temp entities do pvs only
4791                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4792                                         ent->last_trace_visibility = realtime;
4793                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4794                                         r_refdef.viewcache.entityvisible[i] = 0;
4795                         }
4796                 }
4797         }
4798 }
4799
4800 /// only used if skyrendermasked, and normally returns false
4801 int R_DrawBrushModelsSky (void)
4802 {
4803         int i, sky;
4804         entity_render_t *ent;
4805
4806         sky = false;
4807         for (i = 0;i < r_refdef.scene.numentities;i++)
4808         {
4809                 if (!r_refdef.viewcache.entityvisible[i])
4810                         continue;
4811                 ent = r_refdef.scene.entities[i];
4812                 if (!ent->model || !ent->model->DrawSky)
4813                         continue;
4814                 ent->model->DrawSky(ent);
4815                 sky = true;
4816         }
4817         return sky;
4818 }
4819
4820 static void R_DrawNoModel(entity_render_t *ent);
4821 static void R_DrawModels(void)
4822 {
4823         int i;
4824         entity_render_t *ent;
4825
4826         for (i = 0;i < r_refdef.scene.numentities;i++)
4827         {
4828                 if (!r_refdef.viewcache.entityvisible[i])
4829                         continue;
4830                 ent = r_refdef.scene.entities[i];
4831                 r_refdef.stats.entities++;
4832                 /*
4833                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4834                 {
4835                         vec3_t f, l, u, o;
4836                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4837                         Con_Printf("R_DrawModels\n");
4838                         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]);
4839                         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);
4840                         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);
4841                 }
4842                 */
4843                 if (ent->model && ent->model->Draw != NULL)
4844                         ent->model->Draw(ent);
4845                 else
4846                         R_DrawNoModel(ent);
4847         }
4848 }
4849
4850 static void R_DrawModelsDepth(void)
4851 {
4852         int i;
4853         entity_render_t *ent;
4854
4855         for (i = 0;i < r_refdef.scene.numentities;i++)
4856         {
4857                 if (!r_refdef.viewcache.entityvisible[i])
4858                         continue;
4859                 ent = r_refdef.scene.entities[i];
4860                 if (ent->model && ent->model->DrawDepth != NULL)
4861                         ent->model->DrawDepth(ent);
4862         }
4863 }
4864
4865 static void R_DrawModelsDebug(void)
4866 {
4867         int i;
4868         entity_render_t *ent;
4869
4870         for (i = 0;i < r_refdef.scene.numentities;i++)
4871         {
4872                 if (!r_refdef.viewcache.entityvisible[i])
4873                         continue;
4874                 ent = r_refdef.scene.entities[i];
4875                 if (ent->model && ent->model->DrawDebug != NULL)
4876                         ent->model->DrawDebug(ent);
4877         }
4878 }
4879
4880 static void R_DrawModelsAddWaterPlanes(void)
4881 {
4882         int i;
4883         entity_render_t *ent;
4884
4885         for (i = 0;i < r_refdef.scene.numentities;i++)
4886         {
4887                 if (!r_refdef.viewcache.entityvisible[i])
4888                         continue;
4889                 ent = r_refdef.scene.entities[i];
4890                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4891                         ent->model->DrawAddWaterPlanes(ent);
4892         }
4893 }
4894
4895 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4896 {
4897         if (r_hdr_irisadaptation.integer)
4898         {
4899                 vec3_t ambient;
4900                 vec3_t diffuse;
4901                 vec3_t diffusenormal;
4902                 vec_t brightness;
4903                 vec_t goal;
4904                 vec_t adjust;
4905                 vec_t current;
4906                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4907                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4908                 brightness = max(0.0000001f, brightness);
4909                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4910                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4911                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4912                 current = r_hdr_irisadaptation_value.value;
4913                 if (current < goal)
4914                         current = min(current + adjust, goal);
4915                 else if (current > goal)
4916                         current = max(current - adjust, goal);
4917                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4918                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4919         }
4920         else if (r_hdr_irisadaptation_value.value != 1.0f)
4921                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4922 }
4923
4924 static void R_View_SetFrustum(const int *scissor)
4925 {
4926         int i;
4927         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4928         vec3_t forward, left, up, origin, v;
4929
4930         if(scissor)
4931         {
4932                 // flipped x coordinates (because x points left here)
4933                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4934                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4935
4936                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4937                 switch(vid.renderpath)
4938                 {
4939                         case RENDERPATH_D3D9:
4940                         case RENDERPATH_D3D10:
4941                         case RENDERPATH_D3D11:
4942                                 // non-flipped y coordinates
4943                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4944                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4945                                 break;
4946                         case RENDERPATH_SOFT:
4947                         case RENDERPATH_GL11:
4948                         case RENDERPATH_GL13:
4949                         case RENDERPATH_GL20:
4950                         case RENDERPATH_GLES1:
4951                         case RENDERPATH_GLES2:
4952                                 // non-flipped y coordinates
4953                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4954                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4955                                 break;
4956                 }
4957         }
4958
4959         // we can't trust r_refdef.view.forward and friends in reflected scenes
4960         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4961
4962 #if 0
4963         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4964         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4965         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4966         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4967         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4968         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4969         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4970         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4971         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4972         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4973         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4974         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4975 #endif
4976
4977 #if 0
4978         zNear = r_refdef.nearclip;
4979         nudge = 1.0 - 1.0 / (1<<23);
4980         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4981         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4982         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4983         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4984         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4985         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4986         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4987         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4988 #endif
4989
4990
4991
4992 #if 0
4993         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4994         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4995         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4996         r_refdef.view.frustum[0].dist = m[15] - m[12];
4997
4998         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4999         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5000         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5001         r_refdef.view.frustum[1].dist = m[15] + m[12];
5002
5003         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5004         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5005         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5006         r_refdef.view.frustum[2].dist = m[15] - m[13];
5007
5008         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5009         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5010         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5011         r_refdef.view.frustum[3].dist = m[15] + m[13];
5012
5013         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5014         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5015         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5016         r_refdef.view.frustum[4].dist = m[15] - m[14];
5017
5018         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5019         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5020         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5021         r_refdef.view.frustum[5].dist = m[15] + m[14];
5022 #endif
5023
5024         if (r_refdef.view.useperspective)
5025         {
5026                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5027                 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]);
5028                 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]);
5029                 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]);
5030                 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]);
5031
5032                 // then the normals from the corners relative to origin
5033                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5034                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5035                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5036                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5037
5038                 // in a NORMAL view, forward cross left == up
5039                 // in a REFLECTED view, forward cross left == down
5040                 // so our cross products above need to be adjusted for a left handed coordinate system
5041                 CrossProduct(forward, left, v);
5042                 if(DotProduct(v, up) < 0)
5043                 {
5044                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5045                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5046                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5047                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5048                 }
5049
5050                 // Leaving those out was a mistake, those were in the old code, and they
5051                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5052                 // I couldn't reproduce it after adding those normalizations. --blub
5053                 VectorNormalize(r_refdef.view.frustum[0].normal);
5054                 VectorNormalize(r_refdef.view.frustum[1].normal);
5055                 VectorNormalize(r_refdef.view.frustum[2].normal);
5056                 VectorNormalize(r_refdef.view.frustum[3].normal);
5057
5058                 // make the corners absolute
5059                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5060                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5061                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5062                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5063
5064                 // one more normal
5065                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5066
5067                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5068                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5069                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5070                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5071                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5072         }
5073         else
5074         {
5075                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5076                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5077                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5078                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5079                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5081                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5082                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5083                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5084                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5085         }
5086         r_refdef.view.numfrustumplanes = 5;
5087
5088         if (r_refdef.view.useclipplane)
5089         {
5090                 r_refdef.view.numfrustumplanes = 6;
5091                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5092         }
5093
5094         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5095                 PlaneClassify(r_refdef.view.frustum + i);
5096
5097         // LordHavoc: note to all quake engine coders, Quake had a special case
5098         // for 90 degrees which assumed a square view (wrong), so I removed it,
5099         // Quake2 has it disabled as well.
5100
5101         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5102         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5103         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5104         //PlaneClassify(&frustum[0]);
5105
5106         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5107         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5108         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5109         //PlaneClassify(&frustum[1]);
5110
5111         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5112         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5113         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5114         //PlaneClassify(&frustum[2]);
5115
5116         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5117         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5118         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5119         //PlaneClassify(&frustum[3]);
5120
5121         // nearclip plane
5122         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5123         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5124         //PlaneClassify(&frustum[4]);
5125 }
5126
5127 void R_View_UpdateWithScissor(const int *myscissor)
5128 {
5129         R_Main_ResizeViewCache();
5130         R_View_SetFrustum(myscissor);
5131         R_View_WorldVisibility(r_refdef.view.useclipplane);
5132         R_View_UpdateEntityVisible();
5133         R_View_UpdateEntityLighting();
5134 }
5135
5136 void R_View_Update(void)
5137 {
5138         R_Main_ResizeViewCache();
5139         R_View_SetFrustum(NULL);
5140         R_View_WorldVisibility(r_refdef.view.useclipplane);
5141         R_View_UpdateEntityVisible();
5142         R_View_UpdateEntityLighting();
5143 }
5144
5145 float viewscalefpsadjusted = 1.0f;
5146
5147 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5148 {
5149         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5150         scale = bound(0.03125f, scale, 1.0f);
5151         *outwidth = (int)ceil(width * scale);
5152         *outheight = (int)ceil(height * scale);
5153 }
5154
5155 void R_Mesh_SetMainRenderTargets(void)
5156 {
5157         if (r_bloomstate.fbo_framebuffer)
5158                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5159         else
5160                 R_Mesh_ResetRenderTargets();
5161 }
5162
5163 void R_SetupView(qboolean allowwaterclippingplane)
5164 {
5165         const float *customclipplane = NULL;
5166         float plane[4];
5167         int scaledwidth, scaledheight;
5168         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5169         {
5170                 // LordHavoc: couldn't figure out how to make this approach the
5171                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5172                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5173                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5174                         dist = r_refdef.view.clipplane.dist;
5175                 plane[0] = r_refdef.view.clipplane.normal[0];
5176                 plane[1] = r_refdef.view.clipplane.normal[1];
5177                 plane[2] = r_refdef.view.clipplane.normal[2];
5178                 plane[3] = -dist;
5179                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5180         }
5181
5182         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5183         if (!r_refdef.view.useperspective)
5184                 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);
5185         else if (vid.stencil && r_useinfinitefarclip.integer)
5186                 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);
5187         else
5188                 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);
5189         R_Mesh_SetMainRenderTargets();
5190         R_SetViewport(&r_refdef.view.viewport);
5191         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5192         {
5193                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5194                 float screenplane[4];
5195                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5196                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5197                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5198                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5199                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5200         }
5201 }
5202
5203 void R_EntityMatrix(const matrix4x4_t *matrix)
5204 {
5205         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5206         {
5207                 gl_modelmatrixchanged = false;
5208                 gl_modelmatrix = *matrix;
5209                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5210                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5211                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5212                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5213                 CHECKGLERROR
5214                 switch(vid.renderpath)
5215                 {
5216                 case RENDERPATH_D3D9:
5217 #ifdef SUPPORTD3D
5218                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5219                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5220 #endif
5221                         break;
5222                 case RENDERPATH_D3D10:
5223                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5224                         break;
5225                 case RENDERPATH_D3D11:
5226                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5227                         break;
5228                 case RENDERPATH_GL11:
5229                 case RENDERPATH_GL13:
5230                 case RENDERPATH_GLES1:
5231                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5232                         break;
5233                 case RENDERPATH_SOFT:
5234                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5235                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5236                         break;
5237                 case RENDERPATH_GL20:
5238                 case RENDERPATH_GLES2:
5239                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5240                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5241                         break;
5242                 }
5243         }
5244 }
5245
5246 void R_ResetViewRendering2D(void)
5247 {
5248         r_viewport_t viewport;
5249         DrawQ_Finish();
5250
5251         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5252         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);
5253         R_Mesh_ResetRenderTargets();
5254         R_SetViewport(&viewport);
5255         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5256         GL_Color(1, 1, 1, 1);
5257         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5258         GL_BlendFunc(GL_ONE, GL_ZERO);
5259         GL_ScissorTest(false);
5260         GL_DepthMask(false);
5261         GL_DepthRange(0, 1);
5262         GL_DepthTest(false);
5263         GL_DepthFunc(GL_LEQUAL);
5264         R_EntityMatrix(&identitymatrix);
5265         R_Mesh_ResetTextureState();
5266         GL_PolygonOffset(0, 0);
5267         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5268         switch(vid.renderpath)
5269         {
5270         case RENDERPATH_GL11:
5271         case RENDERPATH_GL13:
5272         case RENDERPATH_GL20:
5273         case RENDERPATH_GLES1:
5274         case RENDERPATH_GLES2:
5275                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5276                 break;
5277         case RENDERPATH_D3D9:
5278         case RENDERPATH_D3D10:
5279         case RENDERPATH_D3D11:
5280         case RENDERPATH_SOFT:
5281                 break;
5282         }
5283         GL_CullFace(GL_NONE);
5284 }
5285
5286 void R_ResetViewRendering3D(void)
5287 {
5288         DrawQ_Finish();
5289
5290         R_SetupView(true);
5291         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5292         GL_Color(1, 1, 1, 1);
5293         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5294         GL_BlendFunc(GL_ONE, GL_ZERO);
5295         GL_ScissorTest(true);
5296         GL_DepthMask(true);
5297         GL_DepthRange(0, 1);
5298         GL_DepthTest(true);
5299         GL_DepthFunc(GL_LEQUAL);
5300         R_EntityMatrix(&identitymatrix);
5301         R_Mesh_ResetTextureState();
5302         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5303         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5304         switch(vid.renderpath)
5305         {
5306         case RENDERPATH_GL11:
5307         case RENDERPATH_GL13:
5308         case RENDERPATH_GL20:
5309         case RENDERPATH_GLES1:
5310         case RENDERPATH_GLES2:
5311                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5312                 break;
5313         case RENDERPATH_D3D9:
5314         case RENDERPATH_D3D10:
5315         case RENDERPATH_D3D11:
5316         case RENDERPATH_SOFT:
5317                 break;
5318         }
5319         GL_CullFace(r_refdef.view.cullface_back);
5320 }
5321
5322 /*
5323 ================
5324 R_RenderView_UpdateViewVectors
5325 ================
5326 */
5327 static void R_RenderView_UpdateViewVectors(void)
5328 {
5329         // break apart the view matrix into vectors for various purposes
5330         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5331         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5332         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5333         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5334         // make an inverted copy of the view matrix for tracking sprites
5335         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5336 }
5337
5338 void R_RenderScene(void);
5339 void R_RenderWaterPlanes(void);
5340
5341 static void R_Water_StartFrame(void)
5342 {
5343         int i;
5344         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5345         r_waterstate_waterplane_t *p;
5346
5347         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5348                 return;
5349
5350         switch(vid.renderpath)
5351         {
5352         case RENDERPATH_GL20:
5353         case RENDERPATH_D3D9:
5354         case RENDERPATH_D3D10:
5355         case RENDERPATH_D3D11:
5356         case RENDERPATH_SOFT:
5357         case RENDERPATH_GLES2:
5358                 break;
5359         case RENDERPATH_GL11:
5360         case RENDERPATH_GL13:
5361         case RENDERPATH_GLES1:
5362                 return;
5363         }
5364
5365         // set waterwidth and waterheight to the water resolution that will be
5366         // used (often less than the screen resolution for faster rendering)
5367         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5368
5369         // calculate desired texture sizes
5370         // can't use water if the card does not support the texture size
5371         if (!r_water.integer || r_showsurfaces.integer)
5372                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5373         else if (vid.support.arb_texture_non_power_of_two)
5374         {
5375                 texturewidth = waterwidth;
5376                 textureheight = waterheight;
5377                 camerawidth = waterwidth;
5378                 cameraheight = waterheight;
5379         }
5380         else
5381         {
5382                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5383                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5384                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5385                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5386         }
5387
5388         // allocate textures as needed
5389         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5390         {
5391                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5392                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5393                 {
5394                         if (p->texture_refraction)
5395                                 R_FreeTexture(p->texture_refraction);
5396                         p->texture_refraction = NULL;
5397                         if (p->texture_reflection)
5398                                 R_FreeTexture(p->texture_reflection);
5399                         p->texture_reflection = NULL;
5400                         if (p->texture_camera)
5401                                 R_FreeTexture(p->texture_camera);
5402                         p->texture_camera = NULL;
5403                 }
5404                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5405                 r_waterstate.texturewidth = texturewidth;
5406                 r_waterstate.textureheight = textureheight;
5407                 r_waterstate.camerawidth = camerawidth;
5408                 r_waterstate.cameraheight = cameraheight;
5409         }
5410
5411         if (r_waterstate.texturewidth)
5412         {
5413                 int scaledwidth, scaledheight;
5414
5415                 r_waterstate.enabled = true;
5416
5417                 // when doing a reduced render (HDR) we want to use a smaller area
5418                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5419                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5420                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5421
5422                 // set up variables that will be used in shader setup
5423                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5424                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5425                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5426                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5427         }
5428
5429         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5430         r_waterstate.numwaterplanes = 0;
5431 }
5432
5433 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5434 {
5435         int triangleindex, planeindex;
5436         const int *e;
5437         vec3_t vert[3];
5438         vec3_t normal;
5439         vec3_t center;
5440         mplane_t plane;
5441         r_waterstate_waterplane_t *p;
5442         texture_t *t = R_GetCurrentTexture(surface->texture);
5443
5444         // just use the first triangle with a valid normal for any decisions
5445         VectorClear(normal);
5446         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5447         {
5448                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5449                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5450                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5451                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5452                 if (VectorLength2(normal) >= 0.001)
5453                         break;
5454         }
5455
5456         VectorCopy(normal, plane.normal);
5457         VectorNormalize(plane.normal);
5458         plane.dist = DotProduct(vert[0], plane.normal);
5459         PlaneClassify(&plane);
5460         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5461         {
5462                 // skip backfaces (except if nocullface is set)
5463                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5464                         return;
5465                 VectorNegate(plane.normal, plane.normal);
5466                 plane.dist *= -1;
5467                 PlaneClassify(&plane);
5468         }
5469
5470
5471         // find a matching plane if there is one
5472         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5473                 if(p->camera_entity == t->camera_entity)
5474                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5475                                 break;
5476         if (planeindex >= r_waterstate.maxwaterplanes)
5477                 return; // nothing we can do, out of planes
5478
5479         // if this triangle does not fit any known plane rendered this frame, add one
5480         if (planeindex >= r_waterstate.numwaterplanes)
5481         {
5482                 // store the new plane
5483                 r_waterstate.numwaterplanes++;
5484                 p->plane = plane;
5485                 // clear materialflags and pvs
5486                 p->materialflags = 0;
5487                 p->pvsvalid = false;
5488                 p->camera_entity = t->camera_entity;
5489                 VectorCopy(surface->mins, p->mins);
5490                 VectorCopy(surface->maxs, p->maxs);
5491         }
5492         else
5493         {
5494                 // merge mins/maxs
5495                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5496                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5497                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5498                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5499                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5500                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5501         }
5502         // merge this surface's materialflags into the waterplane
5503         p->materialflags |= t->currentmaterialflags;
5504         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5505         {
5506                 // merge this surface's PVS into the waterplane
5507                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5508                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5509                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5510                 {
5511                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5512                         p->pvsvalid = true;
5513                 }
5514         }
5515 }
5516
5517 static void R_Water_ProcessPlanes(void)
5518 {
5519         int myscissor[4];
5520         r_refdef_view_t originalview;
5521         r_refdef_view_t myview;
5522         int planeindex;
5523         r_waterstate_waterplane_t *p;
5524         vec3_t visorigin;
5525
5526         originalview = r_refdef.view;
5527
5528         // make sure enough textures are allocated
5529         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5530         {
5531                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5532                 {
5533                         if (!p->texture_refraction)
5534                                 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);
5535                         if (!p->texture_refraction)
5536                                 goto error;
5537                 }
5538                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5539                 {
5540                         if (!p->texture_camera)
5541                                 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);
5542                         if (!p->texture_camera)
5543                                 goto error;
5544                 }
5545
5546                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5547                 {
5548                         if (!p->texture_reflection)
5549                                 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);
5550                         if (!p->texture_reflection)
5551                                 goto error;
5552                 }
5553         }
5554
5555         // render views
5556         r_refdef.view = originalview;
5557         r_refdef.view.showdebug = false;
5558         r_refdef.view.width = r_waterstate.waterwidth;
5559         r_refdef.view.height = r_waterstate.waterheight;
5560         r_refdef.view.useclipplane = true;
5561         myview = r_refdef.view;
5562         r_waterstate.renderingscene = true;
5563         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5564         {
5565                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5566                 {
5567                         r_refdef.view = myview;
5568                         if(r_water_scissormode.integer)
5569                         {
5570                                 R_SetupView(true);
5571                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5572                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5573                         }
5574
5575                         // render reflected scene and copy into texture
5576                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5577                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5578                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5579                         r_refdef.view.clipplane = p->plane;
5580
5581                         // reverse the cullface settings for this render
5582                         r_refdef.view.cullface_front = GL_FRONT;
5583                         r_refdef.view.cullface_back = GL_BACK;
5584                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5585                         {
5586                                 r_refdef.view.usecustompvs = true;
5587                                 if (p->pvsvalid)
5588                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5589                                 else
5590                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5591                         }
5592
5593                         R_ResetViewRendering3D();
5594                         R_ClearScreen(r_refdef.fogenabled);
5595                         if(r_water_scissormode.integer & 2)
5596                                 R_View_UpdateWithScissor(myscissor);
5597                         else
5598                                 R_View_Update();
5599                         if(r_water_scissormode.integer & 1)
5600                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5601                         R_RenderScene();
5602
5603                         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);
5604                 }
5605
5606                 // render the normal view scene and copy into texture
5607                 // (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)
5608                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5609                 {
5610                         r_refdef.view = myview;
5611                         if(r_water_scissormode.integer)
5612                         {
5613                                 R_SetupView(true);
5614                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5615                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5616                         }
5617
5618                         r_waterstate.renderingrefraction = true;
5619
5620                         r_refdef.view.clipplane = p->plane;
5621                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5622                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5623
5624                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5625                         {
5626                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5627                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5628                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5629                                 R_RenderView_UpdateViewVectors();
5630                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5631                                 {
5632                                         r_refdef.view.usecustompvs = true;
5633                                         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);
5634                                 }
5635                         }
5636
5637                         PlaneClassify(&r_refdef.view.clipplane);
5638
5639                         R_ResetViewRendering3D();
5640                         R_ClearScreen(r_refdef.fogenabled);
5641                         if(r_water_scissormode.integer & 2)
5642                                 R_View_UpdateWithScissor(myscissor);
5643                         else
5644                                 R_View_Update();
5645                         if(r_water_scissormode.integer & 1)
5646                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5647                         R_RenderScene();
5648
5649                         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);
5650                         r_waterstate.renderingrefraction = false;
5651                 }
5652                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5653                 {
5654                         r_refdef.view = myview;
5655
5656                         r_refdef.view.clipplane = p->plane;
5657                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5658                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5659
5660                         r_refdef.view.width = r_waterstate.camerawidth;
5661                         r_refdef.view.height = r_waterstate.cameraheight;
5662                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5663                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5664
5665                         if(p->camera_entity)
5666                         {
5667                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5668                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5669                         }
5670
5671                         // note: all of the view is used for displaying... so
5672                         // there is no use in scissoring
5673
5674                         // reverse the cullface settings for this render
5675                         r_refdef.view.cullface_front = GL_FRONT;
5676                         r_refdef.view.cullface_back = GL_BACK;
5677                         // also reverse the view matrix
5678                         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
5679                         R_RenderView_UpdateViewVectors();
5680                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5681                         {
5682                                 r_refdef.view.usecustompvs = true;
5683                                 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);
5684                         }
5685                         
5686                         // camera needs no clipplane
5687                         r_refdef.view.useclipplane = false;
5688
5689                         PlaneClassify(&r_refdef.view.clipplane);
5690
5691                         R_ResetViewRendering3D();
5692                         R_ClearScreen(r_refdef.fogenabled);
5693                         R_View_Update();
5694                         R_RenderScene();
5695
5696                         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);
5697                         r_waterstate.renderingrefraction = false;
5698                 }
5699
5700         }
5701         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5702         r_waterstate.renderingscene = false;
5703         r_refdef.view = originalview;
5704         R_ResetViewRendering3D();
5705         R_ClearScreen(r_refdef.fogenabled);
5706         R_View_Update();
5707         return;
5708 error:
5709         r_refdef.view = originalview;
5710         r_waterstate.renderingscene = false;
5711         Cvar_SetValueQuick(&r_water, 0);
5712         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5713         return;
5714 }
5715
5716 void R_Bloom_StartFrame(void)
5717 {
5718         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5719         int viewwidth, viewheight;
5720         textype_t textype;
5721
5722         if (r_viewscale_fpsscaling.integer)
5723         {
5724                 double actualframetime;
5725                 double targetframetime;
5726                 double adjust;
5727                 actualframetime = r_refdef.lastdrawscreentime;
5728                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5729                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5730                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5731                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5732                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5733                 viewscalefpsadjusted += adjust;
5734                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5735         }
5736         else
5737                 viewscalefpsadjusted = 1.0f;
5738
5739         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5740
5741         switch(vid.renderpath)
5742         {
5743         case RENDERPATH_GL20:
5744         case RENDERPATH_D3D9:
5745         case RENDERPATH_D3D10:
5746         case RENDERPATH_D3D11:
5747         case RENDERPATH_SOFT:
5748         case RENDERPATH_GLES2:
5749                 break;
5750         case RENDERPATH_GL11:
5751         case RENDERPATH_GL13:
5752         case RENDERPATH_GLES1:
5753                 return;
5754         }
5755
5756         // set bloomwidth and bloomheight to the bloom resolution that will be
5757         // used (often less than the screen resolution for faster rendering)
5758         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5759         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5760         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5761         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5762         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5763
5764         // calculate desired texture sizes
5765         if (vid.support.arb_texture_non_power_of_two)
5766         {
5767                 screentexturewidth = vid.width;
5768                 screentextureheight = vid.height;
5769                 bloomtexturewidth = r_bloomstate.bloomwidth;
5770                 bloomtextureheight = r_bloomstate.bloomheight;
5771         }
5772         else
5773         {
5774                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5775                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5776                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5777                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5778         }
5779
5780         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))
5781         {
5782                 Cvar_SetValueQuick(&r_hdr, 0);
5783                 Cvar_SetValueQuick(&r_bloom, 0);
5784                 Cvar_SetValueQuick(&r_motionblur, 0);
5785                 Cvar_SetValueQuick(&r_damageblur, 0);
5786         }
5787
5788         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)
5789                 screentexturewidth = screentextureheight = 0;
5790         if (!r_hdr.integer && !r_bloom.integer)
5791                 bloomtexturewidth = bloomtextureheight = 0;
5792
5793         textype = TEXTYPE_COLORBUFFER;
5794         switch (vid.renderpath)
5795         {
5796         case RENDERPATH_GL20:
5797         case RENDERPATH_GLES2:
5798                 if (vid.support.ext_framebuffer_object)
5799                 {
5800                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5801                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5802                 }
5803                 break;
5804         case RENDERPATH_GL11:
5805         case RENDERPATH_GL13:
5806         case RENDERPATH_GLES1:
5807         case RENDERPATH_D3D9:
5808         case RENDERPATH_D3D10:
5809         case RENDERPATH_D3D11:
5810         case RENDERPATH_SOFT:
5811                 break;
5812         }
5813
5814         // allocate textures as needed
5815         if (r_bloomstate.screentexturewidth != screentexturewidth
5816          || r_bloomstate.screentextureheight != screentextureheight
5817          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5818          || r_bloomstate.bloomtextureheight != bloomtextureheight
5819          || r_bloomstate.texturetype != textype
5820          || r_bloomstate.viewfbo != r_viewfbo.integer)
5821         {
5822                 if (r_bloomstate.texture_bloom)
5823                         R_FreeTexture(r_bloomstate.texture_bloom);
5824                 r_bloomstate.texture_bloom = NULL;
5825                 if (r_bloomstate.texture_screen)
5826                         R_FreeTexture(r_bloomstate.texture_screen);
5827                 r_bloomstate.texture_screen = NULL;
5828                 if (r_bloomstate.fbo_framebuffer)
5829                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5830                 r_bloomstate.fbo_framebuffer = 0;
5831                 if (r_bloomstate.texture_framebuffercolor)
5832                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5833                 r_bloomstate.texture_framebuffercolor = NULL;
5834                 if (r_bloomstate.texture_framebufferdepth)
5835                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5836                 r_bloomstate.texture_framebufferdepth = NULL;
5837                 r_bloomstate.screentexturewidth = screentexturewidth;
5838                 r_bloomstate.screentextureheight = screentextureheight;
5839                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5840                         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);
5841                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5842                 {
5843                         // FIXME: choose depth bits based on a cvar
5844                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5845                         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);
5846                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5847                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5848                         // render depth into one texture and normalmap into the other
5849                         if (qglDrawBuffer)
5850                         {
5851                                 int status;
5852                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5853                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5854                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5855                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5856                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5857                         }
5858                 }
5859                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5860                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5861                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5862                         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);
5863                 r_bloomstate.viewfbo = r_viewfbo.integer;
5864                 r_bloomstate.texturetype = textype;
5865         }
5866
5867         // when doing a reduced render (HDR) we want to use a smaller area
5868         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5869         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5870         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5871         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5872         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5873
5874         // set up a texcoord array for the full resolution screen image
5875         // (we have to keep this around to copy back during final render)
5876         r_bloomstate.screentexcoord2f[0] = 0;
5877         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5878         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5879         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5880         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5881         r_bloomstate.screentexcoord2f[5] = 0;
5882         r_bloomstate.screentexcoord2f[6] = 0;
5883         r_bloomstate.screentexcoord2f[7] = 0;
5884
5885         // set up a texcoord array for the reduced resolution bloom image
5886         // (which will be additive blended over the screen image)
5887         r_bloomstate.bloomtexcoord2f[0] = 0;
5888         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5889         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5890         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5892         r_bloomstate.bloomtexcoord2f[5] = 0;
5893         r_bloomstate.bloomtexcoord2f[6] = 0;
5894         r_bloomstate.bloomtexcoord2f[7] = 0;
5895
5896         switch(vid.renderpath)
5897         {
5898         case RENDERPATH_GL11:
5899         case RENDERPATH_GL13:
5900         case RENDERPATH_GL20:
5901         case RENDERPATH_SOFT:
5902         case RENDERPATH_GLES1:
5903         case RENDERPATH_GLES2:
5904                 break;
5905         case RENDERPATH_D3D9:
5906         case RENDERPATH_D3D10:
5907         case RENDERPATH_D3D11:
5908                 {
5909                         int i;
5910                         for (i = 0;i < 4;i++)
5911                         {
5912                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5913                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5914                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5915                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5916                         }
5917                 }
5918                 break;
5919         }
5920
5921         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5922         {
5923                 r_bloomstate.enabled = true;
5924                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5925         }
5926
5927         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);
5928
5929         if (r_bloomstate.fbo_framebuffer)
5930                 r_refdef.view.clear = true;
5931 }
5932
5933 void R_Bloom_CopyBloomTexture(float colorscale)
5934 {
5935         r_refdef.stats.bloom++;
5936
5937         // scale down screen texture to the bloom texture size
5938         CHECKGLERROR
5939         R_Mesh_SetMainRenderTargets();
5940         R_SetViewport(&r_bloomstate.viewport);
5941         GL_BlendFunc(GL_ONE, GL_ZERO);
5942         GL_Color(colorscale, colorscale, colorscale, 1);
5943         // 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...
5944         switch(vid.renderpath)
5945         {
5946         case RENDERPATH_GL11:
5947         case RENDERPATH_GL13:
5948         case RENDERPATH_GL20:
5949         case RENDERPATH_GLES1:
5950         case RENDERPATH_GLES2:
5951         case RENDERPATH_SOFT:
5952                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5953                 break;
5954         case RENDERPATH_D3D9:
5955         case RENDERPATH_D3D10:
5956         case RENDERPATH_D3D11:
5957                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5958                 break;
5959         }
5960         // TODO: do boxfilter scale-down in shader?
5961         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5962         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5963         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5964
5965         // we now have a bloom image in the framebuffer
5966         // copy it into the bloom image texture for later processing
5967         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);
5968         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5969 }
5970
5971 void R_Bloom_CopyHDRTexture(void)
5972 {
5973         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);
5974         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5975 }
5976
5977 void R_Bloom_MakeTexture(void)
5978 {
5979         int x, range, dir;
5980         float xoffset, yoffset, r, brighten;
5981
5982         r_refdef.stats.bloom++;
5983
5984         R_ResetViewRendering2D();
5985
5986         // we have a bloom image in the framebuffer
5987         CHECKGLERROR
5988         R_SetViewport(&r_bloomstate.viewport);
5989
5990         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5991         {
5992                 x *= 2;
5993                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5994                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5995                 GL_Color(r,r,r,1);
5996                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5997                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5998                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5999                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6000
6001                 // copy the vertically blurred bloom view to a texture
6002                 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);
6003                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6004         }
6005
6006         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6007         brighten = r_bloom_brighten.value;
6008         if (r_bloomstate.hdr)
6009                 brighten *= r_hdr_range.value;
6010         brighten = sqrt(brighten);
6011         if(range >= 1)
6012                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6013         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6014
6015         for (dir = 0;dir < 2;dir++)
6016         {
6017                 // blend on at multiple vertical offsets to achieve a vertical blur
6018                 // TODO: do offset blends using GLSL
6019                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6020                 GL_BlendFunc(GL_ONE, GL_ZERO);
6021                 for (x = -range;x <= range;x++)
6022                 {
6023                         if (!dir){xoffset = 0;yoffset = x;}
6024                         else {xoffset = x;yoffset = 0;}
6025                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6026                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6027                         // compute a texcoord array with the specified x and y offset
6028                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6029                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6030                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6031                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6034                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6035                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6036                         // this r value looks like a 'dot' particle, fading sharply to
6037                         // black at the edges
6038                         // (probably not realistic but looks good enough)
6039                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6040                         //r = brighten/(range*2+1);
6041                         r = brighten / (range * 2 + 1);
6042                         if(range >= 1)
6043                                 r *= (1 - x*x/(float)(range*range));
6044                         GL_Color(r, r, r, 1);
6045                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6046                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6047                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6048                         GL_BlendFunc(GL_ONE, GL_ONE);
6049                 }
6050
6051                 // copy the vertically blurred bloom view to a texture
6052                 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);
6053                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6054         }
6055 }
6056
6057 void R_HDR_RenderBloomTexture(void)
6058 {
6059         int oldwidth, oldheight;
6060         float oldcolorscale;
6061         qboolean oldwaterstate;
6062
6063         oldwaterstate = r_waterstate.enabled;
6064         oldcolorscale = r_refdef.view.colorscale;
6065         oldwidth = r_refdef.view.width;
6066         oldheight = r_refdef.view.height;
6067         r_refdef.view.width = r_bloomstate.bloomwidth;
6068         r_refdef.view.height = r_bloomstate.bloomheight;
6069
6070         if(r_hdr.integer < 2)
6071                 r_waterstate.enabled = false;
6072
6073         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6074         // TODO: add exposure compensation features
6075         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6076
6077         r_refdef.view.showdebug = false;
6078         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6079
6080         R_ResetViewRendering3D();
6081
6082         R_ClearScreen(r_refdef.fogenabled);
6083         if (r_timereport_active)
6084                 R_TimeReport("HDRclear");
6085
6086         R_View_Update();
6087         if (r_timereport_active)
6088                 R_TimeReport("visibility");
6089
6090         // only do secondary renders with HDR if r_hdr is 2 or higher
6091         r_waterstate.numwaterplanes = 0;
6092         if (r_waterstate.enabled)
6093                 R_RenderWaterPlanes();
6094
6095         r_refdef.view.showdebug = true;
6096         R_RenderScene();
6097         r_waterstate.numwaterplanes = 0;
6098
6099         R_ResetViewRendering2D();
6100
6101         R_Bloom_CopyHDRTexture();
6102         R_Bloom_MakeTexture();
6103
6104         // restore the view settings
6105         r_waterstate.enabled = oldwaterstate;
6106         r_refdef.view.width = oldwidth;
6107         r_refdef.view.height = oldheight;
6108         r_refdef.view.colorscale = oldcolorscale;
6109
6110         R_ResetViewRendering3D();
6111
6112         R_ClearScreen(r_refdef.fogenabled);
6113         if (r_timereport_active)
6114                 R_TimeReport("viewclear");
6115 }
6116
6117 static void R_BlendView(void)
6118 {
6119         unsigned int permutation;
6120         float uservecs[4][4];
6121
6122         switch (vid.renderpath)
6123         {
6124         case RENDERPATH_GL20:
6125         case RENDERPATH_D3D9:
6126         case RENDERPATH_D3D10:
6127         case RENDERPATH_D3D11:
6128         case RENDERPATH_SOFT:
6129         case RENDERPATH_GLES2:
6130                 permutation =
6131                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6132                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6133                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6134                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6135                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6136
6137                 if (r_bloomstate.texture_screen)
6138                 {
6139                         // make sure the buffer is available
6140                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6141
6142                         R_ResetViewRendering2D();
6143                         R_Mesh_SetMainRenderTargets();
6144
6145                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6146                         {
6147                                 // declare variables
6148                                 float speed;
6149                                 static float avgspeed;
6150
6151                                 speed = VectorLength(cl.movement_velocity);
6152
6153                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6154                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6155
6156                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6157                                 speed = bound(0, speed, 1);
6158                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6159
6160                                 // calculate values into a standard alpha
6161                                 cl.motionbluralpha = 1 - exp(-
6162                                                 (
6163                                                  (r_motionblur.value * speed / 80)
6164                                                  +
6165                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6166                                                 )
6167                                                 /
6168                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6169                                            );
6170
6171                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6172                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6173                                 // apply the blur
6174                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6175                                 {
6176                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6177                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6178                                         switch(vid.renderpath)
6179                                         {
6180                                         case RENDERPATH_GL11:
6181                                         case RENDERPATH_GL13:
6182                                         case RENDERPATH_GL20:
6183                                         case RENDERPATH_GLES1:
6184                                         case RENDERPATH_GLES2:
6185                                         case RENDERPATH_SOFT:
6186                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6187                                                 break;
6188                                         case RENDERPATH_D3D9:
6189                                         case RENDERPATH_D3D10:
6190                                         case RENDERPATH_D3D11:
6191                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6192                                                 break;
6193                                         }
6194                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6195                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6196                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6197                                 }
6198                         }
6199
6200                         // copy view into the screen texture
6201                         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);
6202                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6203                 }
6204                 else if (!r_bloomstate.texture_bloom)
6205                 {
6206                         // we may still have to do view tint...
6207                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6208                         {
6209                                 // apply a color tint to the whole view
6210                                 R_ResetViewRendering2D();
6211                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6212                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6213                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6214                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6215                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6216                         }
6217                         break; // no screen processing, no bloom, skip it
6218                 }
6219
6220                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6221                 {
6222                         // render simple bloom effect
6223                         // copy the screen and shrink it and darken it for the bloom process
6224                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6225                         // make the bloom texture
6226                         R_Bloom_MakeTexture();
6227                 }
6228
6229 #if _MSC_VER >= 1400
6230 #define sscanf sscanf_s
6231 #endif
6232                 memset(uservecs, 0, sizeof(uservecs));
6233                 if (r_glsl_postprocess_uservec1_enable.integer)
6234                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6235                 if (r_glsl_postprocess_uservec2_enable.integer)
6236                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6237                 if (r_glsl_postprocess_uservec3_enable.integer)
6238                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6239                 if (r_glsl_postprocess_uservec4_enable.integer)
6240                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6241
6242                 R_ResetViewRendering2D();
6243                 GL_Color(1, 1, 1, 1);
6244                 GL_BlendFunc(GL_ONE, GL_ZERO);
6245
6246                 switch(vid.renderpath)
6247                 {
6248                 case RENDERPATH_GL20:
6249                 case RENDERPATH_GLES2:
6250                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6251                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6252                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6253                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6254                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6255                         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]);
6256                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6257                         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]);
6258                         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]);
6259                         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]);
6260                         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]);
6261                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6262                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6263                         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);
6264                         break;
6265                 case RENDERPATH_D3D9:
6266 #ifdef SUPPORTD3D
6267                         // 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...
6268                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6269                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6270                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6271                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6272                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6273                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6274                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6275                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6276                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6277                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6278                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6279                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6280                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6281                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6282 #endif
6283                         break;
6284                 case RENDERPATH_D3D10:
6285                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6286                         break;
6287                 case RENDERPATH_D3D11:
6288                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6289                         break;
6290                 case RENDERPATH_SOFT:
6291                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6292                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6293                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6294                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6295                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6296                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6297                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6298                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6299                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6300                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6301                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6302                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6303                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6304                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6305                         break;
6306                 default:
6307                         break;
6308                 }
6309                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6310                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6311                 break;
6312         case RENDERPATH_GL11:
6313         case RENDERPATH_GL13:
6314         case RENDERPATH_GLES1:
6315                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6316                 {
6317                         // apply a color tint to the whole view
6318                         R_ResetViewRendering2D();
6319                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6320                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6321                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6322                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6323                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6324                 }
6325                 break;
6326         }
6327 }
6328
6329 matrix4x4_t r_waterscrollmatrix;
6330
6331 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6332 {
6333         if (r_refdef.fog_density)
6334         {
6335                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6336                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6337                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6338
6339                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6340                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6341                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6342                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6343
6344                 {
6345                         vec3_t fogvec;
6346                         VectorCopy(r_refdef.fogcolor, fogvec);
6347                         //   color.rgb *= ContrastBoost * SceneBrightness;
6348                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6349                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6350                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6351                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6352                 }
6353         }
6354 }
6355
6356 void R_UpdateVariables(void)
6357 {
6358         R_Textures_Frame();
6359
6360         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6361
6362         r_refdef.farclip = r_farclip_base.value;
6363         if (r_refdef.scene.worldmodel)
6364                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6365         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6366
6367         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6368                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6369         r_refdef.polygonfactor = 0;
6370         r_refdef.polygonoffset = 0;
6371         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6372         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6373
6374         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6375         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6376         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6377         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6378         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6379         if (FAKELIGHT_ENABLED)
6380         {
6381                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6382         }
6383         if (r_showsurfaces.integer)
6384         {
6385                 r_refdef.scene.rtworld = false;
6386                 r_refdef.scene.rtworldshadows = false;
6387                 r_refdef.scene.rtdlight = false;
6388                 r_refdef.scene.rtdlightshadows = false;
6389                 r_refdef.lightmapintensity = 0;
6390         }
6391
6392         if (gamemode == GAME_NEHAHRA)
6393         {
6394                 if (gl_fogenable.integer)
6395                 {
6396                         r_refdef.oldgl_fogenable = true;
6397                         r_refdef.fog_density = gl_fogdensity.value;
6398                         r_refdef.fog_red = gl_fogred.value;
6399                         r_refdef.fog_green = gl_foggreen.value;
6400                         r_refdef.fog_blue = gl_fogblue.value;
6401                         r_refdef.fog_alpha = 1;
6402                         r_refdef.fog_start = 0;
6403                         r_refdef.fog_end = gl_skyclip.value;
6404                         r_refdef.fog_height = 1<<30;
6405                         r_refdef.fog_fadedepth = 128;
6406                 }
6407                 else if (r_refdef.oldgl_fogenable)
6408                 {
6409                         r_refdef.oldgl_fogenable = false;
6410                         r_refdef.fog_density = 0;
6411                         r_refdef.fog_red = 0;
6412                         r_refdef.fog_green = 0;
6413                         r_refdef.fog_blue = 0;
6414                         r_refdef.fog_alpha = 0;
6415                         r_refdef.fog_start = 0;
6416                         r_refdef.fog_end = 0;
6417                         r_refdef.fog_height = 1<<30;
6418                         r_refdef.fog_fadedepth = 128;
6419                 }
6420         }
6421
6422         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6423         r_refdef.fog_start = max(0, r_refdef.fog_start);
6424         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6425
6426         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6427
6428         if (r_refdef.fog_density && r_drawfog.integer)
6429         {
6430                 r_refdef.fogenabled = true;
6431                 // this is the point where the fog reaches 0.9986 alpha, which we
6432                 // consider a good enough cutoff point for the texture
6433                 // (0.9986 * 256 == 255.6)
6434                 if (r_fog_exp2.integer)
6435                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6436                 else
6437                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6438                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6439                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6440                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6441                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6442                         R_BuildFogHeightTexture();
6443                 // fog color was already set
6444                 // update the fog texture
6445                 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)
6446                         R_BuildFogTexture();
6447                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6448                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6449         }
6450         else
6451                 r_refdef.fogenabled = false;
6452
6453         switch(vid.renderpath)
6454         {
6455         case RENDERPATH_GL20:
6456         case RENDERPATH_D3D9:
6457         case RENDERPATH_D3D10:
6458         case RENDERPATH_D3D11:
6459         case RENDERPATH_SOFT:
6460         case RENDERPATH_GLES2:
6461                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6462                 {
6463                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6464                         {
6465                                 // build GLSL gamma texture
6466 #define RAMPWIDTH 256
6467                                 unsigned short ramp[RAMPWIDTH * 3];
6468                                 unsigned char rampbgr[RAMPWIDTH][4];
6469                                 int i;
6470
6471                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6472
6473                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6474                                 for(i = 0; i < RAMPWIDTH; ++i)
6475                                 {
6476                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6477                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6478                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6479                                         rampbgr[i][3] = 0;
6480                                 }
6481                                 if (r_texture_gammaramps)
6482                                 {
6483                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6484                                 }
6485                                 else
6486                                 {
6487                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6488                                 }
6489                         }
6490                 }
6491                 else
6492                 {
6493                         // remove GLSL gamma texture
6494                 }
6495                 break;
6496         case RENDERPATH_GL11:
6497         case RENDERPATH_GL13:
6498         case RENDERPATH_GLES1:
6499                 break;
6500         }
6501 }
6502
6503 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6504 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6505 /*
6506 ================
6507 R_SelectScene
6508 ================
6509 */
6510 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6511         if( scenetype != r_currentscenetype ) {
6512                 // store the old scenetype
6513                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6514                 r_currentscenetype = scenetype;
6515                 // move in the new scene
6516                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6517         }
6518 }
6519
6520 /*
6521 ================
6522 R_GetScenePointer
6523 ================
6524 */
6525 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6526 {
6527         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6528         if( scenetype == r_currentscenetype ) {
6529                 return &r_refdef.scene;
6530         } else {
6531                 return &r_scenes_store[ scenetype ];
6532         }
6533 }
6534
6535 /*
6536 ================
6537 R_RenderView
6538 ================
6539 */
6540 int dpsoftrast_test;
6541 void R_RenderView(void)
6542 {
6543         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6544
6545         dpsoftrast_test = r_test.integer;
6546
6547         if (r_timereport_active)
6548                 R_TimeReport("start");
6549         r_textureframe++; // used only by R_GetCurrentTexture
6550         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6551
6552         if(R_CompileShader_CheckStaticParms())
6553                 R_GLSL_Restart_f();
6554
6555         if (!r_drawentities.integer)
6556                 r_refdef.scene.numentities = 0;
6557
6558         R_AnimCache_ClearCache();
6559         R_FrameData_NewFrame();
6560
6561         /* adjust for stereo display */
6562         if(R_Stereo_Active())
6563         {
6564                 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);
6565                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6566         }
6567
6568         if (r_refdef.view.isoverlay)
6569         {
6570                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6571                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6572                 R_TimeReport("depthclear");
6573
6574                 r_refdef.view.showdebug = false;
6575
6576                 r_waterstate.enabled = false;
6577                 r_waterstate.numwaterplanes = 0;
6578
6579                 R_RenderScene();
6580
6581                 r_refdef.view.matrix = originalmatrix;
6582
6583                 CHECKGLERROR
6584                 return;
6585         }
6586
6587         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6588         {
6589                 r_refdef.view.matrix = originalmatrix;
6590                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6591         }
6592
6593         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6594
6595         R_RenderView_UpdateViewVectors();
6596
6597         R_Shadow_UpdateWorldLightSelection();
6598
6599         R_Bloom_StartFrame();
6600         R_Water_StartFrame();
6601
6602         CHECKGLERROR
6603         if (r_timereport_active)
6604                 R_TimeReport("viewsetup");
6605
6606         R_ResetViewRendering3D();
6607
6608         if (r_refdef.view.clear || r_refdef.fogenabled)
6609         {
6610                 R_ClearScreen(r_refdef.fogenabled);
6611                 if (r_timereport_active)
6612                         R_TimeReport("viewclear");
6613         }
6614         r_refdef.view.clear = true;
6615
6616         // this produces a bloom texture to be used in R_BlendView() later
6617         if (r_bloomstate.hdr)
6618         {
6619                 R_HDR_RenderBloomTexture();
6620                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6621                 r_textureframe++; // used only by R_GetCurrentTexture
6622         }
6623
6624         r_refdef.view.showdebug = true;
6625
6626         R_View_Update();
6627         if (r_timereport_active)
6628                 R_TimeReport("visibility");
6629
6630         r_waterstate.numwaterplanes = 0;
6631         if (r_waterstate.enabled)
6632                 R_RenderWaterPlanes();
6633
6634         R_RenderScene();
6635         r_waterstate.numwaterplanes = 0;
6636
6637         R_BlendView();
6638         if (r_timereport_active)
6639                 R_TimeReport("blendview");
6640
6641         GL_Scissor(0, 0, vid.width, vid.height);
6642         GL_ScissorTest(false);
6643
6644         r_refdef.view.matrix = originalmatrix;
6645
6646         CHECKGLERROR
6647 }
6648
6649 void R_RenderWaterPlanes(void)
6650 {
6651         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6652         {
6653                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6654                 if (r_timereport_active)
6655                         R_TimeReport("waterworld");
6656         }
6657
6658         // don't let sound skip if going slow
6659         if (r_refdef.scene.extraupdate)
6660                 S_ExtraUpdate ();
6661
6662         R_DrawModelsAddWaterPlanes();
6663         if (r_timereport_active)
6664                 R_TimeReport("watermodels");
6665
6666         if (r_waterstate.numwaterplanes)
6667         {
6668                 R_Water_ProcessPlanes();
6669                 if (r_timereport_active)
6670                         R_TimeReport("waterscenes");
6671         }
6672 }
6673
6674 extern void R_DrawLightningBeams (void);
6675 extern void VM_CL_AddPolygonsToMeshQueue (void);
6676 extern void R_DrawPortals (void);
6677 extern cvar_t cl_locs_show;
6678 static void R_DrawLocs(void);
6679 static void R_DrawEntityBBoxes(void);
6680 static void R_DrawModelDecals(void);
6681 extern void R_DrawModelShadows(void);
6682 extern void R_DrawModelShadowMaps(void);
6683 extern cvar_t cl_decals_newsystem;
6684 extern qboolean r_shadow_usingdeferredprepass;
6685 void R_RenderScene(void)
6686 {
6687         qboolean shadowmapping = false;
6688
6689         if (r_timereport_active)
6690                 R_TimeReport("beginscene");
6691
6692         r_refdef.stats.renders++;
6693
6694         R_UpdateFogColor();
6695
6696         // don't let sound skip if going slow
6697         if (r_refdef.scene.extraupdate)
6698                 S_ExtraUpdate ();
6699
6700         R_MeshQueue_BeginScene();
6701
6702         R_SkyStartFrame();
6703
6704         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);
6705
6706         if (r_timereport_active)
6707                 R_TimeReport("skystartframe");
6708
6709         if (cl.csqc_vidvars.drawworld)
6710         {
6711                 // don't let sound skip if going slow
6712                 if (r_refdef.scene.extraupdate)
6713                         S_ExtraUpdate ();
6714
6715                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6716                 {
6717                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6718                         if (r_timereport_active)
6719                                 R_TimeReport("worldsky");
6720                 }
6721
6722                 if (R_DrawBrushModelsSky() && r_timereport_active)
6723                         R_TimeReport("bmodelsky");
6724
6725                 if (skyrendermasked && skyrenderlater)
6726                 {
6727                         // we have to force off the water clipping plane while rendering sky
6728                         R_SetupView(false);
6729                         R_Sky();
6730                         R_SetupView(true);
6731                         if (r_timereport_active)
6732                                 R_TimeReport("sky");
6733                 }
6734         }
6735
6736         R_AnimCache_CacheVisibleEntities();
6737         if (r_timereport_active)
6738                 R_TimeReport("animation");
6739
6740         R_Shadow_PrepareLights();
6741         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6742                 R_Shadow_PrepareModelShadows();
6743         if (r_timereport_active)
6744                 R_TimeReport("preparelights");
6745
6746         if (R_Shadow_ShadowMappingEnabled())
6747                 shadowmapping = true;
6748
6749         if (r_shadow_usingdeferredprepass)
6750                 R_Shadow_DrawPrepass();
6751
6752         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6753         {
6754                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6755                 if (r_timereport_active)
6756                         R_TimeReport("worlddepth");
6757         }
6758         if (r_depthfirst.integer >= 2)
6759         {
6760                 R_DrawModelsDepth();
6761                 if (r_timereport_active)
6762                         R_TimeReport("modeldepth");
6763         }
6764
6765         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6766         {
6767                 R_DrawModelShadowMaps();
6768                 R_ResetViewRendering3D();
6769                 // don't let sound skip if going slow
6770                 if (r_refdef.scene.extraupdate)
6771                         S_ExtraUpdate ();
6772         }
6773
6774         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6775         {
6776                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6777                 if (r_timereport_active)
6778                         R_TimeReport("world");
6779         }
6780
6781         // don't let sound skip if going slow
6782         if (r_refdef.scene.extraupdate)
6783                 S_ExtraUpdate ();
6784
6785         R_DrawModels();
6786         if (r_timereport_active)
6787                 R_TimeReport("models");
6788
6789         // don't let sound skip if going slow
6790         if (r_refdef.scene.extraupdate)
6791                 S_ExtraUpdate ();
6792
6793         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6794         {
6795                 R_DrawModelShadows();
6796                 R_ResetViewRendering3D();
6797                 // don't let sound skip if going slow
6798                 if (r_refdef.scene.extraupdate)
6799                         S_ExtraUpdate ();
6800         }
6801
6802         if (!r_shadow_usingdeferredprepass)
6803         {
6804                 R_Shadow_DrawLights();
6805                 if (r_timereport_active)
6806                         R_TimeReport("rtlights");
6807         }
6808
6809         // don't let sound skip if going slow
6810         if (r_refdef.scene.extraupdate)
6811                 S_ExtraUpdate ();
6812
6813         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6814         {
6815                 R_DrawModelShadows();
6816                 R_ResetViewRendering3D();
6817                 // don't let sound skip if going slow
6818                 if (r_refdef.scene.extraupdate)
6819                         S_ExtraUpdate ();
6820         }
6821
6822         if (cl.csqc_vidvars.drawworld)
6823         {
6824                 if (cl_decals_newsystem.integer)
6825                 {
6826                         R_DrawModelDecals();
6827                         if (r_timereport_active)
6828                                 R_TimeReport("modeldecals");
6829                 }
6830                 else
6831                 {
6832                         R_DrawDecals();
6833                         if (r_timereport_active)
6834                                 R_TimeReport("decals");
6835                 }
6836
6837                 R_DrawParticles();
6838                 if (r_timereport_active)
6839                         R_TimeReport("particles");
6840
6841                 R_DrawExplosions();
6842                 if (r_timereport_active)
6843                         R_TimeReport("explosions");
6844
6845                 R_DrawLightningBeams();
6846                 if (r_timereport_active)
6847                         R_TimeReport("lightning");
6848         }
6849
6850         VM_CL_AddPolygonsToMeshQueue();
6851
6852         if (r_refdef.view.showdebug)
6853         {
6854                 if (cl_locs_show.integer)
6855                 {
6856                         R_DrawLocs();
6857                         if (r_timereport_active)
6858                                 R_TimeReport("showlocs");
6859                 }
6860
6861                 if (r_drawportals.integer)
6862                 {
6863                         R_DrawPortals();
6864                         if (r_timereport_active)
6865                                 R_TimeReport("portals");
6866                 }
6867
6868                 if (r_showbboxes.value > 0)
6869                 {
6870                         R_DrawEntityBBoxes();
6871                         if (r_timereport_active)
6872                                 R_TimeReport("bboxes");
6873                 }
6874         }
6875
6876         if (r_transparent.integer)
6877         {
6878                 R_MeshQueue_RenderTransparent();
6879                 if (r_timereport_active)
6880                         R_TimeReport("drawtrans");
6881         }
6882
6883         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))
6884         {
6885                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6886                 if (r_timereport_active)
6887                         R_TimeReport("worlddebug");
6888                 R_DrawModelsDebug();
6889                 if (r_timereport_active)
6890                         R_TimeReport("modeldebug");
6891         }
6892
6893         if (cl.csqc_vidvars.drawworld)
6894         {
6895                 R_Shadow_DrawCoronas();
6896                 if (r_timereport_active)
6897                         R_TimeReport("coronas");
6898         }
6899
6900 #if 0
6901         {
6902                 GL_DepthTest(false);
6903                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6904                 GL_Color(1, 1, 1, 1);
6905                 qglBegin(GL_POLYGON);
6906                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6907                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6908                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6909                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6910                 qglEnd();
6911                 qglBegin(GL_POLYGON);
6912                 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]);
6913                 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]);
6914                 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]);
6915                 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]);
6916                 qglEnd();
6917                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6918         }
6919 #endif
6920
6921         // don't let sound skip if going slow
6922         if (r_refdef.scene.extraupdate)
6923                 S_ExtraUpdate ();
6924
6925         R_ResetViewRendering2D();
6926 }
6927
6928 static const unsigned short bboxelements[36] =
6929 {
6930         5, 1, 3, 5, 3, 7,
6931         6, 2, 0, 6, 0, 4,
6932         7, 3, 2, 7, 2, 6,
6933         4, 0, 1, 4, 1, 5,
6934         4, 5, 7, 4, 7, 6,
6935         1, 0, 2, 1, 2, 3,
6936 };
6937
6938 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6939 {
6940         int i;
6941         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6942
6943         RSurf_ActiveWorldEntity();
6944
6945         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6946         GL_DepthMask(false);
6947         GL_DepthRange(0, 1);
6948         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6949 //      R_Mesh_ResetTextureState();
6950
6951         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6952         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6953         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6954         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6955         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6956         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6957         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6958         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6959         R_FillColors(color4f, 8, cr, cg, cb, ca);
6960         if (r_refdef.fogenabled)
6961         {
6962                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6963                 {
6964                         f1 = RSurf_FogVertex(v);
6965                         f2 = 1 - f1;
6966                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6967                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6968                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6969                 }
6970         }
6971         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6972         R_Mesh_ResetTextureState();
6973         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6974         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6975 }
6976
6977 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6978 {
6979         int i;
6980         float color[4];
6981         prvm_edict_t *edict;
6982         prvm_prog_t *prog_save = prog;
6983
6984         // this function draws bounding boxes of server entities
6985         if (!sv.active)
6986                 return;
6987
6988         GL_CullFace(GL_NONE);
6989         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6990
6991         prog = 0;
6992         SV_VM_Begin();
6993         for (i = 0;i < numsurfaces;i++)
6994         {
6995                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6996                 switch ((int)edict->fields.server->solid)
6997                 {
6998                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
6999                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7000                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7001                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7002                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7003                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7004                 }
7005                 color[3] *= r_showbboxes.value;
7006                 color[3] = bound(0, color[3], 1);
7007                 GL_DepthTest(!r_showdisabledepthtest.integer);
7008                 GL_CullFace(r_refdef.view.cullface_front);
7009                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7010         }
7011         SV_VM_End();
7012         prog = prog_save;
7013 }
7014
7015 static void R_DrawEntityBBoxes(void)
7016 {
7017         int i;
7018         prvm_edict_t *edict;
7019         vec3_t center;
7020         prvm_prog_t *prog_save = prog;
7021
7022         // this function draws bounding boxes of server entities
7023         if (!sv.active)
7024                 return;
7025
7026         prog = 0;
7027         SV_VM_Begin();
7028         for (i = 0;i < prog->num_edicts;i++)
7029         {
7030                 edict = PRVM_EDICT_NUM(i);
7031                 if (edict->priv.server->free)
7032                         continue;
7033                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7034                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7035                         continue;
7036                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7037                         continue;
7038                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7039                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7040         }
7041         SV_VM_End();
7042         prog = prog_save;
7043 }
7044
7045 static const int nomodelelement3i[24] =
7046 {
7047         5, 2, 0,
7048         5, 1, 2,
7049         5, 0, 3,
7050         5, 3, 1,
7051         0, 2, 4,
7052         2, 1, 4,
7053         3, 0, 4,
7054         1, 3, 4
7055 };
7056
7057 static const unsigned short nomodelelement3s[24] =
7058 {
7059         5, 2, 0,
7060         5, 1, 2,
7061         5, 0, 3,
7062         5, 3, 1,
7063         0, 2, 4,
7064         2, 1, 4,
7065         3, 0, 4,
7066         1, 3, 4
7067 };
7068
7069 static const float nomodelvertex3f[6*3] =
7070 {
7071         -16,   0,   0,
7072          16,   0,   0,
7073           0, -16,   0,
7074           0,  16,   0,
7075           0,   0, -16,
7076           0,   0,  16
7077 };
7078
7079 static const float nomodelcolor4f[6*4] =
7080 {
7081         0.0f, 0.0f, 0.5f, 1.0f,
7082         0.0f, 0.0f, 0.5f, 1.0f,
7083         0.0f, 0.5f, 0.0f, 1.0f,
7084         0.0f, 0.5f, 0.0f, 1.0f,
7085         0.5f, 0.0f, 0.0f, 1.0f,
7086         0.5f, 0.0f, 0.0f, 1.0f
7087 };
7088
7089 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7090 {
7091         int i;
7092         float f1, f2, *c;
7093         float color4f[6*4];
7094
7095         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);
7096
7097         // this is only called once per entity so numsurfaces is always 1, and
7098         // surfacelist is always {0}, so this code does not handle batches
7099
7100         if (rsurface.ent_flags & RENDER_ADDITIVE)
7101         {
7102                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7103                 GL_DepthMask(false);
7104         }
7105         else if (rsurface.colormod[3] < 1)
7106         {
7107                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7108                 GL_DepthMask(false);
7109         }
7110         else
7111         {
7112                 GL_BlendFunc(GL_ONE, GL_ZERO);
7113                 GL_DepthMask(true);
7114         }
7115         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7116         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7117         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7118         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7119         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7120         for (i = 0, c = color4f;i < 6;i++, c += 4)
7121         {
7122                 c[0] *= rsurface.colormod[0];
7123                 c[1] *= rsurface.colormod[1];
7124                 c[2] *= rsurface.colormod[2];
7125                 c[3] *= rsurface.colormod[3];
7126         }
7127         if (r_refdef.fogenabled)
7128         {
7129                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7130                 {
7131                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7132                         f2 = 1 - f1;
7133                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7134                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7135                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7136                 }
7137         }
7138 //      R_Mesh_ResetTextureState();
7139         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7140         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7141         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7142 }
7143
7144 void R_DrawNoModel(entity_render_t *ent)
7145 {
7146         vec3_t org;
7147         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7148         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7149                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7150         else
7151                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7152 }
7153
7154 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7155 {
7156         vec3_t right1, right2, diff, normal;
7157
7158         VectorSubtract (org2, org1, normal);
7159
7160         // calculate 'right' vector for start
7161         VectorSubtract (r_refdef.view.origin, org1, diff);
7162         CrossProduct (normal, diff, right1);
7163         VectorNormalize (right1);
7164
7165         // calculate 'right' vector for end
7166         VectorSubtract (r_refdef.view.origin, org2, diff);
7167         CrossProduct (normal, diff, right2);
7168         VectorNormalize (right2);
7169
7170         vert[ 0] = org1[0] + width * right1[0];
7171         vert[ 1] = org1[1] + width * right1[1];
7172         vert[ 2] = org1[2] + width * right1[2];
7173         vert[ 3] = org1[0] - width * right1[0];
7174         vert[ 4] = org1[1] - width * right1[1];
7175         vert[ 5] = org1[2] - width * right1[2];
7176         vert[ 6] = org2[0] - width * right2[0];
7177         vert[ 7] = org2[1] - width * right2[1];
7178         vert[ 8] = org2[2] - width * right2[2];
7179         vert[ 9] = org2[0] + width * right2[0];
7180         vert[10] = org2[1] + width * right2[1];
7181         vert[11] = org2[2] + width * right2[2];
7182 }
7183
7184 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)
7185 {
7186         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7187         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7188         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7189         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7190         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7191         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7192         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7193         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7194         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7195         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7196         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7197         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7198 }
7199
7200 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7201 {
7202         int i;
7203         float *vertex3f;
7204         float v[3];
7205         VectorSet(v, x, y, z);
7206         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7207                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7208                         break;
7209         if (i == mesh->numvertices)
7210         {
7211                 if (mesh->numvertices < mesh->maxvertices)
7212                 {
7213                         VectorCopy(v, vertex3f);
7214                         mesh->numvertices++;
7215                 }
7216                 return mesh->numvertices;
7217         }
7218         else
7219                 return i;
7220 }
7221
7222 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7223 {
7224         int i;
7225         int *e, element[3];
7226         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7227         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7228         e = mesh->element3i + mesh->numtriangles * 3;
7229         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7230         {
7231                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7232                 if (mesh->numtriangles < mesh->maxtriangles)
7233                 {
7234                         *e++ = element[0];
7235                         *e++ = element[1];
7236                         *e++ = element[2];
7237                         mesh->numtriangles++;
7238                 }
7239                 element[1] = element[2];
7240         }
7241 }
7242
7243 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7244 {
7245         int i;
7246         int *e, element[3];
7247         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7248         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7249         e = mesh->element3i + mesh->numtriangles * 3;
7250         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7251         {
7252                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7253                 if (mesh->numtriangles < mesh->maxtriangles)
7254                 {
7255                         *e++ = element[0];
7256                         *e++ = element[1];
7257                         *e++ = element[2];
7258                         mesh->numtriangles++;
7259                 }
7260                 element[1] = element[2];
7261         }
7262 }
7263
7264 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7265 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7266 {
7267         int planenum, planenum2;
7268         int w;
7269         int tempnumpoints;
7270         mplane_t *plane, *plane2;
7271         double maxdist;
7272         double temppoints[2][256*3];
7273         // figure out how large a bounding box we need to properly compute this brush
7274         maxdist = 0;
7275         for (w = 0;w < numplanes;w++)
7276                 maxdist = max(maxdist, fabs(planes[w].dist));
7277         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7278         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7279         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7280         {
7281                 w = 0;
7282                 tempnumpoints = 4;
7283                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7284                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7285                 {
7286                         if (planenum2 == planenum)
7287                                 continue;
7288                         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);
7289                         w = !w;
7290                 }
7291                 if (tempnumpoints < 3)
7292                         continue;
7293                 // generate elements forming a triangle fan for this polygon
7294                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7295         }
7296 }
7297
7298 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)
7299 {
7300         texturelayer_t *layer;
7301         layer = t->currentlayers + t->currentnumlayers++;
7302         layer->type = type;
7303         layer->depthmask = depthmask;
7304         layer->blendfunc1 = blendfunc1;
7305         layer->blendfunc2 = blendfunc2;
7306         layer->texture = texture;
7307         layer->texmatrix = *matrix;
7308         layer->color[0] = r;
7309         layer->color[1] = g;
7310         layer->color[2] = b;
7311         layer->color[3] = a;
7312 }
7313
7314 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7315 {
7316         if(parms[0] == 0 && parms[1] == 0)
7317                 return false;
7318         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7319                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7320                         return false;
7321         return true;
7322 }
7323
7324 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7325 {
7326         double index, f;
7327         index = parms[2] + r_refdef.scene.time * parms[3];
7328         index -= floor(index);
7329         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7330         {
7331         default:
7332         case Q3WAVEFUNC_NONE:
7333         case Q3WAVEFUNC_NOISE:
7334         case Q3WAVEFUNC_COUNT:
7335                 f = 0;
7336                 break;
7337         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7338         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7339         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7340         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7341         case Q3WAVEFUNC_TRIANGLE:
7342                 index *= 4;
7343                 f = index - floor(index);
7344                 if (index < 1)
7345                         f = f;
7346                 else if (index < 2)
7347                         f = 1 - f;
7348                 else if (index < 3)
7349                         f = -f;
7350                 else
7351                         f = -(1 - f);
7352                 break;
7353         }
7354         f = parms[0] + parms[1] * f;
7355         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7356                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7357         return (float) f;
7358 }
7359
7360 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7361 {
7362         int w, h, idx;
7363         float f;
7364         float tcmat[12];
7365         matrix4x4_t matrix, temp;
7366         switch(tcmod->tcmod)
7367         {
7368                 case Q3TCMOD_COUNT:
7369                 case Q3TCMOD_NONE:
7370                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7371                                 matrix = r_waterscrollmatrix;
7372                         else
7373                                 matrix = identitymatrix;
7374                         break;
7375                 case Q3TCMOD_ENTITYTRANSLATE:
7376                         // this is used in Q3 to allow the gamecode to control texcoord
7377                         // scrolling on the entity, which is not supported in darkplaces yet.
7378                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7379                         break;
7380                 case Q3TCMOD_ROTATE:
7381                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7382                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7383                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7384                         break;
7385                 case Q3TCMOD_SCALE:
7386                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7387                         break;
7388                 case Q3TCMOD_SCROLL:
7389                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7390                         break;
7391                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7392                         w = (int) tcmod->parms[0];
7393                         h = (int) tcmod->parms[1];
7394                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7395                         f = f - floor(f);
7396                         idx = (int) floor(f * w * h);
7397                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7398                         break;
7399                 case Q3TCMOD_STRETCH:
7400                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7401                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7402                         break;
7403                 case Q3TCMOD_TRANSFORM:
7404                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7405                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7406                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7407                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7408                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7409                         break;
7410                 case Q3TCMOD_TURBULENT:
7411                         // this is handled in the RSurf_PrepareVertices function
7412                         matrix = identitymatrix;
7413                         break;
7414         }
7415         temp = *texmatrix;
7416         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7417 }
7418
7419 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7420 {
7421         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7422         char name[MAX_QPATH];
7423         skinframe_t *skinframe;
7424         unsigned char pixels[296*194];
7425         strlcpy(cache->name, skinname, sizeof(cache->name));
7426         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7427         if (developer_loading.integer)
7428                 Con_Printf("loading %s\n", name);
7429         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7430         if (!skinframe || !skinframe->base)
7431         {
7432                 unsigned char *f;
7433                 fs_offset_t filesize;
7434                 skinframe = NULL;
7435                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7436                 if (f)
7437                 {
7438                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7439                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7440                         Mem_Free(f);
7441                 }
7442         }
7443         cache->skinframe = skinframe;
7444 }
7445
7446 texture_t *R_GetCurrentTexture(texture_t *t)
7447 {
7448         int i;
7449         const entity_render_t *ent = rsurface.entity;
7450         dp_model_t *model = ent->model;
7451         q3shaderinfo_layer_tcmod_t *tcmod;
7452
7453         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7454                 return t->currentframe;
7455         t->update_lastrenderframe = r_textureframe;
7456         t->update_lastrenderentity = (void *)ent;
7457
7458         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7459                 t->camera_entity = ent->entitynumber;
7460         else
7461                 t->camera_entity = 0;
7462
7463         // switch to an alternate material if this is a q1bsp animated material
7464         {
7465                 texture_t *texture = t;
7466                 int s = rsurface.ent_skinnum;
7467                 if ((unsigned int)s >= (unsigned int)model->numskins)
7468                         s = 0;
7469                 if (model->skinscenes)
7470                 {
7471                         if (model->skinscenes[s].framecount > 1)
7472                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7473                         else
7474                                 s = model->skinscenes[s].firstframe;
7475                 }
7476                 if (s > 0)
7477                         t = t + s * model->num_surfaces;
7478                 if (t->animated)
7479                 {
7480                         // use an alternate animation if the entity's frame is not 0,
7481                         // and only if the texture has an alternate animation
7482                         if (rsurface.ent_alttextures && t->anim_total[1])
7483                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7484                         else
7485                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7486                 }
7487                 texture->currentframe = t;
7488         }
7489
7490         // update currentskinframe to be a qw skin or animation frame
7491         if (rsurface.ent_qwskin >= 0)
7492         {
7493                 i = rsurface.ent_qwskin;
7494                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7495                 {
7496                         r_qwskincache_size = cl.maxclients;
7497                         if (r_qwskincache)
7498                                 Mem_Free(r_qwskincache);
7499                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7500                 }
7501                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7502                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7503                 t->currentskinframe = r_qwskincache[i].skinframe;
7504                 if (t->currentskinframe == NULL)
7505                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7506         }
7507         else if (t->numskinframes >= 2)
7508                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7509         if (t->backgroundnumskinframes >= 2)
7510                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7511
7512         t->currentmaterialflags = t->basematerialflags;
7513         t->currentalpha = rsurface.colormod[3];
7514         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7515                 t->currentalpha *= r_wateralpha.value;
7516         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7517                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7518         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7519                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7520         if (!(rsurface.ent_flags & RENDER_LIGHT))
7521                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7522         else if (FAKELIGHT_ENABLED)
7523         {
7524                 // no modellight if using fakelight for the map
7525         }
7526         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7527         {
7528                 // pick a model lighting mode
7529                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7530                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7531                 else
7532                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7533         }
7534         if (rsurface.ent_flags & RENDER_ADDITIVE)
7535                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7536         else if (t->currentalpha < 1)
7537                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7539                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7540         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7541                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7542         if (t->backgroundnumskinframes)
7543                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7544         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7545         {
7546                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7547                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7548         }
7549         else
7550                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7551         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7552                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7553
7554         // there is no tcmod
7555         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7556         {
7557                 t->currenttexmatrix = r_waterscrollmatrix;
7558                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7559         }
7560         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7561         {
7562                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7563                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7564         }
7565
7566         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7567                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7568         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7570
7571         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7572         if (t->currentskinframe->qpixels)
7573                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7574         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7575         if (!t->basetexture)
7576                 t->basetexture = r_texture_notexture;
7577         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7578         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7579         t->nmaptexture = t->currentskinframe->nmap;
7580         if (!t->nmaptexture)
7581                 t->nmaptexture = r_texture_blanknormalmap;
7582         t->glosstexture = r_texture_black;
7583         t->glowtexture = t->currentskinframe->glow;
7584         t->fogtexture = t->currentskinframe->fog;
7585         t->reflectmasktexture = t->currentskinframe->reflect;
7586         if (t->backgroundnumskinframes)
7587         {
7588                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7589                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7590                 t->backgroundglosstexture = r_texture_black;
7591                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7592                 if (!t->backgroundnmaptexture)
7593                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7594         }
7595         else
7596         {
7597                 t->backgroundbasetexture = r_texture_white;
7598                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7599                 t->backgroundglosstexture = r_texture_black;
7600                 t->backgroundglowtexture = NULL;
7601         }
7602         t->specularpower = r_shadow_glossexponent.value;
7603         // TODO: store reference values for these in the texture?
7604         t->specularscale = 0;
7605         if (r_shadow_gloss.integer > 0)
7606         {
7607                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7608                 {
7609                         if (r_shadow_glossintensity.value > 0)
7610                         {
7611                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7612                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7613                                 t->specularscale = r_shadow_glossintensity.value;
7614                         }
7615                 }
7616                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7617                 {
7618                         t->glosstexture = r_texture_white;
7619                         t->backgroundglosstexture = r_texture_white;
7620                         t->specularscale = r_shadow_gloss2intensity.value;
7621                         t->specularpower = r_shadow_gloss2exponent.value;
7622                 }
7623         }
7624         t->specularscale *= t->specularscalemod;
7625         t->specularpower *= t->specularpowermod;
7626
7627         // lightmaps mode looks bad with dlights using actual texturing, so turn
7628         // off the colormap and glossmap, but leave the normalmap on as it still
7629         // accurately represents the shading involved
7630         if (gl_lightmaps.integer)
7631         {
7632                 t->basetexture = r_texture_grey128;
7633                 t->pantstexture = r_texture_black;
7634                 t->shirttexture = r_texture_black;
7635                 t->nmaptexture = r_texture_blanknormalmap;
7636                 t->glosstexture = r_texture_black;
7637                 t->glowtexture = NULL;
7638                 t->fogtexture = NULL;
7639                 t->reflectmasktexture = NULL;
7640                 t->backgroundbasetexture = NULL;
7641                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7642                 t->backgroundglosstexture = r_texture_black;
7643                 t->backgroundglowtexture = NULL;
7644                 t->specularscale = 0;
7645                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7646         }
7647
7648         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7649         VectorClear(t->dlightcolor);
7650         t->currentnumlayers = 0;
7651         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7652         {
7653                 int blendfunc1, blendfunc2;
7654                 qboolean depthmask;
7655                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7656                 {
7657                         blendfunc1 = GL_SRC_ALPHA;
7658                         blendfunc2 = GL_ONE;
7659                 }
7660                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7661                 {
7662                         blendfunc1 = GL_SRC_ALPHA;
7663                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7664                 }
7665                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7666                 {
7667                         blendfunc1 = t->customblendfunc[0];
7668                         blendfunc2 = t->customblendfunc[1];
7669                 }
7670                 else
7671                 {
7672                         blendfunc1 = GL_ONE;
7673                         blendfunc2 = GL_ZERO;
7674                 }
7675                 // don't colormod evilblend textures
7676                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7677                         VectorSet(t->lightmapcolor, 1, 1, 1);
7678                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7679                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7680                 {
7681                         // fullbright is not affected by r_refdef.lightmapintensity
7682                         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]);
7683                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7684                                 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]);
7685                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7686                                 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]);
7687                 }
7688                 else
7689                 {
7690                         vec3_t ambientcolor;
7691                         float colorscale;
7692                         // set the color tint used for lights affecting this surface
7693                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7694                         colorscale = 2;
7695                         // q3bsp has no lightmap updates, so the lightstylevalue that
7696                         // would normally be baked into the lightmap must be
7697                         // applied to the color
7698                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7699                         if (model->type == mod_brushq3)
7700                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7701                         colorscale *= r_refdef.lightmapintensity;
7702                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7703                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7704                         // basic lit geometry
7705                         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]);
7706                         // add pants/shirt if needed
7707                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7708                                 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]);
7709                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7710                                 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]);
7711                         // now add ambient passes if needed
7712                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7713                         {
7714                                 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]);
7715                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7716                                         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]);
7717                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7718                                         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]);
7719                         }
7720                 }
7721                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7722                         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]);
7723                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7724                 {
7725                         // if this is opaque use alpha blend which will darken the earlier
7726                         // passes cheaply.
7727                         //
7728                         // if this is an alpha blended material, all the earlier passes
7729                         // were darkened by fog already, so we only need to add the fog
7730                         // color ontop through the fog mask texture
7731                         //
7732                         // if this is an additive blended material, all the earlier passes
7733                         // were darkened by fog already, and we should not add fog color
7734                         // (because the background was not darkened, there is no fog color
7735                         // that was lost behind it).
7736                         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]);
7737                 }
7738         }
7739
7740         return t->currentframe;
7741 }
7742
7743 rsurfacestate_t rsurface;
7744
7745 void RSurf_ActiveWorldEntity(void)
7746 {
7747         dp_model_t *model = r_refdef.scene.worldmodel;
7748         //if (rsurface.entity == r_refdef.scene.worldentity)
7749         //      return;
7750         rsurface.entity = r_refdef.scene.worldentity;
7751         rsurface.skeleton = NULL;
7752         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7753         rsurface.ent_skinnum = 0;
7754         rsurface.ent_qwskin = -1;
7755         rsurface.ent_shadertime = 0;
7756         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7757         rsurface.matrix = identitymatrix;
7758         rsurface.inversematrix = identitymatrix;
7759         rsurface.matrixscale = 1;
7760         rsurface.inversematrixscale = 1;
7761         R_EntityMatrix(&identitymatrix);
7762         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7763         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7764         rsurface.fograngerecip = r_refdef.fograngerecip;
7765         rsurface.fogheightfade = r_refdef.fogheightfade;
7766         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7767         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7768         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7769         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7770         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7771         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7772         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7773         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7774         rsurface.colormod[3] = 1;
7775         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);
7776         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7777         rsurface.frameblend[0].lerp = 1;
7778         rsurface.ent_alttextures = false;
7779         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7780         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7781         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7782         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7784         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7785         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7787         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7788         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7790         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7791         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7793         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7794         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7796         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7797         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7798         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7799         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7800         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7801         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7802         rsurface.modelelement3i = model->surfmesh.data_element3i;
7803         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7804         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7805         rsurface.modelelement3s = model->surfmesh.data_element3s;
7806         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7807         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7808         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7809         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7810         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7811         rsurface.modelsurfaces = model->data_surfaces;
7812         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7813         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7814         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7815         rsurface.modelgeneratedvertex = false;
7816         rsurface.batchgeneratedvertex = false;
7817         rsurface.batchfirstvertex = 0;
7818         rsurface.batchnumvertices = 0;
7819         rsurface.batchfirsttriangle = 0;
7820         rsurface.batchnumtriangles = 0;
7821         rsurface.batchvertex3f  = NULL;
7822         rsurface.batchvertex3f_vertexbuffer = NULL;
7823         rsurface.batchvertex3f_bufferoffset = 0;
7824         rsurface.batchsvector3f = NULL;
7825         rsurface.batchsvector3f_vertexbuffer = NULL;
7826         rsurface.batchsvector3f_bufferoffset = 0;
7827         rsurface.batchtvector3f = NULL;
7828         rsurface.batchtvector3f_vertexbuffer = NULL;
7829         rsurface.batchtvector3f_bufferoffset = 0;
7830         rsurface.batchnormal3f  = NULL;
7831         rsurface.batchnormal3f_vertexbuffer = NULL;
7832         rsurface.batchnormal3f_bufferoffset = 0;
7833         rsurface.batchlightmapcolor4f = NULL;
7834         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7835         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7836         rsurface.batchtexcoordtexture2f = NULL;
7837         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7838         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7839         rsurface.batchtexcoordlightmap2f = NULL;
7840         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7841         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7842         rsurface.batchvertexmesh = NULL;
7843         rsurface.batchvertexmeshbuffer = NULL;
7844         rsurface.batchvertex3fbuffer = NULL;
7845         rsurface.batchelement3i = NULL;
7846         rsurface.batchelement3i_indexbuffer = NULL;
7847         rsurface.batchelement3i_bufferoffset = 0;
7848         rsurface.batchelement3s = NULL;
7849         rsurface.batchelement3s_indexbuffer = NULL;
7850         rsurface.batchelement3s_bufferoffset = 0;
7851         rsurface.passcolor4f = NULL;
7852         rsurface.passcolor4f_vertexbuffer = NULL;
7853         rsurface.passcolor4f_bufferoffset = 0;
7854 }
7855
7856 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7857 {
7858         dp_model_t *model = ent->model;
7859         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7860         //      return;
7861         rsurface.entity = (entity_render_t *)ent;
7862         rsurface.skeleton = ent->skeleton;
7863         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7864         rsurface.ent_skinnum = ent->skinnum;
7865         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;
7866         rsurface.ent_shadertime = ent->shadertime;
7867         rsurface.ent_flags = ent->flags;
7868         rsurface.matrix = ent->matrix;
7869         rsurface.inversematrix = ent->inversematrix;
7870         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7871         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7872         R_EntityMatrix(&rsurface.matrix);
7873         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7874         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7875         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7876         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7877         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7878         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7879         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7880         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7881         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7882         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7883         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7884         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7885         rsurface.colormod[3] = ent->alpha;
7886         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7887         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7888         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7889         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7890         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7891         if (ent->model->brush.submodel && !prepass)
7892         {
7893                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7894                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7895         }
7896         if (model->surfmesh.isanimated && model->AnimateVertices)
7897         {
7898                 if (ent->animcache_vertex3f)
7899                 {
7900                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7901                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7902                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7903                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7904                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7905                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7906                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7907                 }
7908                 else if (wanttangents)
7909                 {
7910                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7911                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7912                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7915                         rsurface.modelvertexmesh = NULL;
7916                         rsurface.modelvertexmeshbuffer = NULL;
7917                         rsurface.modelvertex3fbuffer = NULL;
7918                 }
7919                 else if (wantnormals)
7920                 {
7921                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7922                         rsurface.modelsvector3f = NULL;
7923                         rsurface.modeltvector3f = NULL;
7924                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7925                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7926                         rsurface.modelvertexmesh = NULL;
7927                         rsurface.modelvertexmeshbuffer = NULL;
7928                         rsurface.modelvertex3fbuffer = NULL;
7929                 }
7930                 else
7931                 {
7932                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7933                         rsurface.modelsvector3f = NULL;
7934                         rsurface.modeltvector3f = NULL;
7935                         rsurface.modelnormal3f = NULL;
7936                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7937                         rsurface.modelvertexmesh = NULL;
7938                         rsurface.modelvertexmeshbuffer = NULL;
7939                         rsurface.modelvertex3fbuffer = NULL;
7940                 }
7941                 rsurface.modelvertex3f_vertexbuffer = 0;
7942                 rsurface.modelvertex3f_bufferoffset = 0;
7943                 rsurface.modelsvector3f_vertexbuffer = 0;
7944                 rsurface.modelsvector3f_bufferoffset = 0;
7945                 rsurface.modeltvector3f_vertexbuffer = 0;
7946                 rsurface.modeltvector3f_bufferoffset = 0;
7947                 rsurface.modelnormal3f_vertexbuffer = 0;
7948                 rsurface.modelnormal3f_bufferoffset = 0;
7949                 rsurface.modelgeneratedvertex = true;
7950         }
7951         else
7952         {
7953                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7954                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7955                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7956                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7957                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7958                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7959                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7960                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7961                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7962                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7963                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7964                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7965                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7966                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7967                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7968                 rsurface.modelgeneratedvertex = false;
7969         }
7970         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7971         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7972         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7973         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7974         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7975         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7976         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7977         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7978         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7979         rsurface.modelelement3i = model->surfmesh.data_element3i;
7980         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7981         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7982         rsurface.modelelement3s = model->surfmesh.data_element3s;
7983         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7984         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7985         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7986         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7987         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7988         rsurface.modelsurfaces = model->data_surfaces;
7989         rsurface.batchgeneratedvertex = false;
7990         rsurface.batchfirstvertex = 0;
7991         rsurface.batchnumvertices = 0;
7992         rsurface.batchfirsttriangle = 0;
7993         rsurface.batchnumtriangles = 0;
7994         rsurface.batchvertex3f  = NULL;
7995         rsurface.batchvertex3f_vertexbuffer = NULL;
7996         rsurface.batchvertex3f_bufferoffset = 0;
7997         rsurface.batchsvector3f = NULL;
7998         rsurface.batchsvector3f_vertexbuffer = NULL;
7999         rsurface.batchsvector3f_bufferoffset = 0;
8000         rsurface.batchtvector3f = NULL;
8001         rsurface.batchtvector3f_vertexbuffer = NULL;
8002         rsurface.batchtvector3f_bufferoffset = 0;
8003         rsurface.batchnormal3f  = NULL;
8004         rsurface.batchnormal3f_vertexbuffer = NULL;
8005         rsurface.batchnormal3f_bufferoffset = 0;
8006         rsurface.batchlightmapcolor4f = NULL;
8007         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8008         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8009         rsurface.batchtexcoordtexture2f = NULL;
8010         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8011         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8012         rsurface.batchtexcoordlightmap2f = NULL;
8013         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8014         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8015         rsurface.batchvertexmesh = NULL;
8016         rsurface.batchvertexmeshbuffer = NULL;
8017         rsurface.batchvertex3fbuffer = NULL;
8018         rsurface.batchelement3i = NULL;
8019         rsurface.batchelement3i_indexbuffer = NULL;
8020         rsurface.batchelement3i_bufferoffset = 0;
8021         rsurface.batchelement3s = NULL;
8022         rsurface.batchelement3s_indexbuffer = NULL;
8023         rsurface.batchelement3s_bufferoffset = 0;
8024         rsurface.passcolor4f = NULL;
8025         rsurface.passcolor4f_vertexbuffer = NULL;
8026         rsurface.passcolor4f_bufferoffset = 0;
8027 }
8028
8029 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)
8030 {
8031         rsurface.entity = r_refdef.scene.worldentity;
8032         rsurface.skeleton = NULL;
8033         rsurface.ent_skinnum = 0;
8034         rsurface.ent_qwskin = -1;
8035         rsurface.ent_shadertime = shadertime;
8036         rsurface.ent_flags = entflags;
8037         rsurface.modelnumvertices = numvertices;
8038         rsurface.modelnumtriangles = numtriangles;
8039         rsurface.matrix = *matrix;
8040         rsurface.inversematrix = *inversematrix;
8041         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8042         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8043         R_EntityMatrix(&rsurface.matrix);
8044         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8045         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8046         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8047         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8048         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8049         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8050         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8051         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8052         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8053         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8054         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8055         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8056         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8057         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8058         rsurface.frameblend[0].lerp = 1;
8059         rsurface.ent_alttextures = false;
8060         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8061         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8062         if (wanttangents)
8063         {
8064                 rsurface.modelvertex3f = (float *)vertex3f;
8065                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8066                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8067                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068         }
8069         else if (wantnormals)
8070         {
8071                 rsurface.modelvertex3f = (float *)vertex3f;
8072                 rsurface.modelsvector3f = NULL;
8073                 rsurface.modeltvector3f = NULL;
8074                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8075         }
8076         else
8077         {
8078                 rsurface.modelvertex3f = (float *)vertex3f;
8079                 rsurface.modelsvector3f = NULL;
8080                 rsurface.modeltvector3f = NULL;
8081                 rsurface.modelnormal3f = NULL;
8082         }
8083         rsurface.modelvertexmesh = NULL;
8084         rsurface.modelvertexmeshbuffer = NULL;
8085         rsurface.modelvertex3fbuffer = NULL;
8086         rsurface.modelvertex3f_vertexbuffer = 0;
8087         rsurface.modelvertex3f_bufferoffset = 0;
8088         rsurface.modelsvector3f_vertexbuffer = 0;
8089         rsurface.modelsvector3f_bufferoffset = 0;
8090         rsurface.modeltvector3f_vertexbuffer = 0;
8091         rsurface.modeltvector3f_bufferoffset = 0;
8092         rsurface.modelnormal3f_vertexbuffer = 0;
8093         rsurface.modelnormal3f_bufferoffset = 0;
8094         rsurface.modelgeneratedvertex = true;
8095         rsurface.modellightmapcolor4f  = (float *)color4f;
8096         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8097         rsurface.modellightmapcolor4f_bufferoffset = 0;
8098         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8099         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8100         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8101         rsurface.modeltexcoordlightmap2f  = NULL;
8102         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8103         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8104         rsurface.modelelement3i = (int *)element3i;
8105         rsurface.modelelement3i_indexbuffer = NULL;
8106         rsurface.modelelement3i_bufferoffset = 0;
8107         rsurface.modelelement3s = (unsigned short *)element3s;
8108         rsurface.modelelement3s_indexbuffer = NULL;
8109         rsurface.modelelement3s_bufferoffset = 0;
8110         rsurface.modellightmapoffsets = NULL;
8111         rsurface.modelsurfaces = NULL;
8112         rsurface.batchgeneratedvertex = false;
8113         rsurface.batchfirstvertex = 0;
8114         rsurface.batchnumvertices = 0;
8115         rsurface.batchfirsttriangle = 0;
8116         rsurface.batchnumtriangles = 0;
8117         rsurface.batchvertex3f  = NULL;
8118         rsurface.batchvertex3f_vertexbuffer = NULL;
8119         rsurface.batchvertex3f_bufferoffset = 0;
8120         rsurface.batchsvector3f = NULL;
8121         rsurface.batchsvector3f_vertexbuffer = NULL;
8122         rsurface.batchsvector3f_bufferoffset = 0;
8123         rsurface.batchtvector3f = NULL;
8124         rsurface.batchtvector3f_vertexbuffer = NULL;
8125         rsurface.batchtvector3f_bufferoffset = 0;
8126         rsurface.batchnormal3f  = NULL;
8127         rsurface.batchnormal3f_vertexbuffer = NULL;
8128         rsurface.batchnormal3f_bufferoffset = 0;
8129         rsurface.batchlightmapcolor4f = NULL;
8130         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8131         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8132         rsurface.batchtexcoordtexture2f = NULL;
8133         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8134         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8135         rsurface.batchtexcoordlightmap2f = NULL;
8136         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8137         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8138         rsurface.batchvertexmesh = NULL;
8139         rsurface.batchvertexmeshbuffer = NULL;
8140         rsurface.batchvertex3fbuffer = NULL;
8141         rsurface.batchelement3i = NULL;
8142         rsurface.batchelement3i_indexbuffer = NULL;
8143         rsurface.batchelement3i_bufferoffset = 0;
8144         rsurface.batchelement3s = NULL;
8145         rsurface.batchelement3s_indexbuffer = NULL;
8146         rsurface.batchelement3s_bufferoffset = 0;
8147         rsurface.passcolor4f = NULL;
8148         rsurface.passcolor4f_vertexbuffer = NULL;
8149         rsurface.passcolor4f_bufferoffset = 0;
8150
8151         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8152         {
8153                 if ((wantnormals || wanttangents) && !normal3f)
8154                 {
8155                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8156                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8157                 }
8158                 if (wanttangents && !svector3f)
8159                 {
8160                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8161                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8162                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8163                 }
8164         }
8165 }
8166
8167 float RSurf_FogPoint(const float *v)
8168 {
8169         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8170         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8171         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8172         float FogHeightFade = r_refdef.fogheightfade;
8173         float fogfrac;
8174         unsigned int fogmasktableindex;
8175         if (r_refdef.fogplaneviewabove)
8176                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8177         else
8178                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8179         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8180         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8181 }
8182
8183 float RSurf_FogVertex(const float *v)
8184 {
8185         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8186         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8187         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8188         float FogHeightFade = rsurface.fogheightfade;
8189         float fogfrac;
8190         unsigned int fogmasktableindex;
8191         if (r_refdef.fogplaneviewabove)
8192                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8193         else
8194                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8195         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8196         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8197 }
8198
8199 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8200 {
8201         int i;
8202         for (i = 0;i < numelements;i++)
8203                 outelement3i[i] = inelement3i[i] + adjust;
8204 }
8205
8206 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8207 extern cvar_t gl_vbo;
8208 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8209 {
8210         int deformindex;
8211         int firsttriangle;
8212         int numtriangles;
8213         int firstvertex;
8214         int endvertex;
8215         int numvertices;
8216         int surfacefirsttriangle;
8217         int surfacenumtriangles;
8218         int surfacefirstvertex;
8219         int surfaceendvertex;
8220         int surfacenumvertices;
8221         int batchnumvertices;
8222         int batchnumtriangles;
8223         int needsupdate;
8224         int i, j;
8225         qboolean gaps;
8226         qboolean dynamicvertex;
8227         float amplitude;
8228         float animpos;
8229         float scale;
8230         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8231         float waveparms[4];
8232         q3shaderinfo_deform_t *deform;
8233         const msurface_t *surface, *firstsurface;
8234         r_vertexmesh_t *vertexmesh;
8235         if (!texturenumsurfaces)
8236                 return;
8237         // find vertex range of this surface batch
8238         gaps = false;
8239         firstsurface = texturesurfacelist[0];
8240         firsttriangle = firstsurface->num_firsttriangle;
8241         batchnumvertices = 0;
8242         batchnumtriangles = 0;
8243         firstvertex = endvertex = firstsurface->num_firstvertex;
8244         for (i = 0;i < texturenumsurfaces;i++)
8245         {
8246                 surface = texturesurfacelist[i];
8247                 if (surface != firstsurface + i)
8248                         gaps = true;
8249                 surfacefirstvertex = surface->num_firstvertex;
8250                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8251                 surfacenumvertices = surface->num_vertices;
8252                 surfacenumtriangles = surface->num_triangles;
8253                 if (firstvertex > surfacefirstvertex)
8254                         firstvertex = surfacefirstvertex;
8255                 if (endvertex < surfaceendvertex)
8256                         endvertex = surfaceendvertex;
8257                 batchnumvertices += surfacenumvertices;
8258                 batchnumtriangles += surfacenumtriangles;
8259         }
8260
8261         // we now know the vertex range used, and if there are any gaps in it
8262         rsurface.batchfirstvertex = firstvertex;
8263         rsurface.batchnumvertices = endvertex - firstvertex;
8264         rsurface.batchfirsttriangle = firsttriangle;
8265         rsurface.batchnumtriangles = batchnumtriangles;
8266
8267         // this variable holds flags for which properties have been updated that
8268         // may require regenerating vertexmesh array...
8269         needsupdate = 0;
8270
8271         // check if any dynamic vertex processing must occur
8272         dynamicvertex = false;
8273
8274         // if there is a chance of animated vertex colors, it's a dynamic batch
8275         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8276         {
8277                 dynamicvertex = true;
8278                 batchneed |= BATCHNEED_NOGAPS;
8279                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8280         }
8281
8282         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8283         {
8284                 switch (deform->deform)
8285                 {
8286                 default:
8287                 case Q3DEFORM_PROJECTIONSHADOW:
8288                 case Q3DEFORM_TEXT0:
8289                 case Q3DEFORM_TEXT1:
8290                 case Q3DEFORM_TEXT2:
8291                 case Q3DEFORM_TEXT3:
8292                 case Q3DEFORM_TEXT4:
8293                 case Q3DEFORM_TEXT5:
8294                 case Q3DEFORM_TEXT6:
8295                 case Q3DEFORM_TEXT7:
8296                 case Q3DEFORM_NONE:
8297                         break;
8298                 case Q3DEFORM_AUTOSPRITE:
8299                         dynamicvertex = true;
8300                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8301                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8302                         break;
8303                 case Q3DEFORM_AUTOSPRITE2:
8304                         dynamicvertex = true;
8305                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8306                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8307                         break;
8308                 case Q3DEFORM_NORMAL:
8309                         dynamicvertex = true;
8310                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8311                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8312                         break;
8313                 case Q3DEFORM_WAVE:
8314                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8315                                 break; // if wavefunc is a nop, ignore this transform
8316                         dynamicvertex = true;
8317                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8318                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8319                         break;
8320                 case Q3DEFORM_BULGE:
8321                         dynamicvertex = true;
8322                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8323                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8324                         break;
8325                 case Q3DEFORM_MOVE:
8326                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8327                                 break; // if wavefunc is a nop, ignore this transform
8328                         dynamicvertex = true;
8329                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8330                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8331                         break;
8332                 }
8333         }
8334         switch(rsurface.texture->tcgen.tcgen)
8335         {
8336         default:
8337         case Q3TCGEN_TEXTURE:
8338                 break;
8339         case Q3TCGEN_LIGHTMAP:
8340                 dynamicvertex = true;
8341                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8342                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8343                 break;
8344         case Q3TCGEN_VECTOR:
8345                 dynamicvertex = true;
8346                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8347                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8348                 break;
8349         case Q3TCGEN_ENVIRONMENT:
8350                 dynamicvertex = true;
8351                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8352                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8353                 break;
8354         }
8355         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8356         {
8357                 dynamicvertex = true;
8358                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8359                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8360         }
8361
8362         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8363         {
8364                 dynamicvertex = true;
8365                 batchneed |= BATCHNEED_NOGAPS;
8366                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8367         }
8368
8369         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8370         {
8371                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8372                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8373                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8374                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8375                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8376                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8377                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8378         }
8379
8380         // when the model data has no vertex buffer (dynamic mesh), we need to
8381         // eliminate gaps
8382         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8383                 batchneed |= BATCHNEED_NOGAPS;
8384
8385         // if needsupdate, we have to do a dynamic vertex batch for sure
8386         if (needsupdate & batchneed)
8387                 dynamicvertex = true;
8388
8389         // see if we need to build vertexmesh from arrays
8390         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8391                 dynamicvertex = true;
8392
8393         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8394         // also some drivers strongly dislike firstvertex
8395         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8396                 dynamicvertex = true;
8397
8398         rsurface.batchvertex3f = rsurface.modelvertex3f;
8399         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8400         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8401         rsurface.batchsvector3f = rsurface.modelsvector3f;
8402         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8403         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8404         rsurface.batchtvector3f = rsurface.modeltvector3f;
8405         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8406         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8407         rsurface.batchnormal3f = rsurface.modelnormal3f;
8408         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8409         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8410         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8411         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8412         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8413         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8414         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8415         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8416         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8417         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8418         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8419         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8420         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8421         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8422         rsurface.batchelement3i = rsurface.modelelement3i;
8423         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8424         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8425         rsurface.batchelement3s = rsurface.modelelement3s;
8426         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8427         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8428
8429         // if any dynamic vertex processing has to occur in software, we copy the
8430         // entire surface list together before processing to rebase the vertices
8431         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8432         //
8433         // if any gaps exist and we do not have a static vertex buffer, we have to
8434         // copy the surface list together to avoid wasting upload bandwidth on the
8435         // vertices in the gaps.
8436         //
8437         // if gaps exist and we have a static vertex buffer, we still have to
8438         // combine the index buffer ranges into one dynamic index buffer.
8439         //
8440         // in all cases we end up with data that can be drawn in one call.
8441
8442         if (!dynamicvertex)
8443         {
8444                 // static vertex data, just set pointers...
8445                 rsurface.batchgeneratedvertex = false;
8446                 // if there are gaps, we want to build a combined index buffer,
8447                 // otherwise use the original static buffer with an appropriate offset
8448                 if (gaps)
8449                 {
8450                         // build a new triangle elements array for this batch
8451                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8452                         rsurface.batchfirsttriangle = 0;
8453                         numtriangles = 0;
8454                         for (i = 0;i < texturenumsurfaces;i++)
8455                         {
8456                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8457                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8458                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8459                                 numtriangles += surfacenumtriangles;
8460                         }
8461                         rsurface.batchelement3i_indexbuffer = NULL;
8462                         rsurface.batchelement3i_bufferoffset = 0;
8463                         rsurface.batchelement3s = NULL;
8464                         rsurface.batchelement3s_indexbuffer = NULL;
8465                         rsurface.batchelement3s_bufferoffset = 0;
8466                         if (endvertex <= 65536)
8467                         {
8468                                 // make a 16bit (unsigned short) index array if possible
8469                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8470                                 for (i = 0;i < numtriangles*3;i++)
8471                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8472                         }
8473                 }
8474                 return;
8475         }
8476
8477         // something needs software processing, do it for real...
8478         // we only directly handle separate array data in this case and then
8479         // generate interleaved data if needed...
8480         rsurface.batchgeneratedvertex = true;
8481
8482         // now copy the vertex data into a combined array and make an index array
8483         // (this is what Quake3 does all the time)
8484         //if (gaps || rsurface.batchfirstvertex)
8485         {
8486                 rsurface.batchvertex3fbuffer = NULL;
8487                 rsurface.batchvertexmesh = NULL;
8488                 rsurface.batchvertexmeshbuffer = NULL;
8489                 rsurface.batchvertex3f = NULL;
8490                 rsurface.batchvertex3f_vertexbuffer = NULL;
8491                 rsurface.batchvertex3f_bufferoffset = 0;
8492                 rsurface.batchsvector3f = NULL;
8493                 rsurface.batchsvector3f_vertexbuffer = NULL;
8494                 rsurface.batchsvector3f_bufferoffset = 0;
8495                 rsurface.batchtvector3f = NULL;
8496                 rsurface.batchtvector3f_vertexbuffer = NULL;
8497                 rsurface.batchtvector3f_bufferoffset = 0;
8498                 rsurface.batchnormal3f = NULL;
8499                 rsurface.batchnormal3f_vertexbuffer = NULL;
8500                 rsurface.batchnormal3f_bufferoffset = 0;
8501                 rsurface.batchlightmapcolor4f = NULL;
8502                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8503                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8504                 rsurface.batchtexcoordtexture2f = NULL;
8505                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8506                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8507                 rsurface.batchtexcoordlightmap2f = NULL;
8508                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8509                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8510                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8511                 rsurface.batchelement3i_indexbuffer = NULL;
8512                 rsurface.batchelement3i_bufferoffset = 0;
8513                 rsurface.batchelement3s = NULL;
8514                 rsurface.batchelement3s_indexbuffer = NULL;
8515                 rsurface.batchelement3s_bufferoffset = 0;
8516                 // we'll only be setting up certain arrays as needed
8517                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8518                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8519                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8520                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8521                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8522                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8524                 {
8525                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8526                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8527                 }
8528                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8529                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8530                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8531                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8532                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8533                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534                 numvertices = 0;
8535                 numtriangles = 0;
8536                 for (i = 0;i < texturenumsurfaces;i++)
8537                 {
8538                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8539                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8540                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8541                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8542                         // copy only the data requested
8543                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8544                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8545                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8546                         {
8547                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8548                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8549                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8550                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8552                                 {
8553                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8554                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8555                                 }
8556                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8557                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8558                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8559                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8560                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8561                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8562                         }
8563                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8564                         numvertices += surfacenumvertices;
8565                         numtriangles += surfacenumtriangles;
8566                 }
8567
8568                 // generate a 16bit index array as well if possible
8569                 // (in general, dynamic batches fit)
8570                 if (numvertices <= 65536)
8571                 {
8572                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8573                         for (i = 0;i < numtriangles*3;i++)
8574                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8575                 }
8576
8577                 // since we've copied everything, the batch now starts at 0
8578                 rsurface.batchfirstvertex = 0;
8579                 rsurface.batchnumvertices = batchnumvertices;
8580                 rsurface.batchfirsttriangle = 0;
8581                 rsurface.batchnumtriangles = batchnumtriangles;
8582         }
8583
8584         // q1bsp surfaces rendered in vertex color mode have to have colors
8585         // calculated based on lightstyles
8586         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8587         {
8588                 // generate color arrays for the surfaces in this list
8589                 int c[4];
8590                 int scale;
8591                 int size3;
8592                 const int *offsets;
8593                 const unsigned char *lm;
8594                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8595                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8596                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8597                 numvertices = 0;
8598                 for (i = 0;i < texturenumsurfaces;i++)
8599                 {
8600                         surface = texturesurfacelist[i];
8601                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8602                         surfacenumvertices = surface->num_vertices;
8603                         if (surface->lightmapinfo->samples)
8604                         {
8605                                 for (j = 0;j < surfacenumvertices;j++)
8606                                 {
8607                                         lm = surface->lightmapinfo->samples + offsets[j];
8608                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8609                                         VectorScale(lm, scale, c);
8610                                         if (surface->lightmapinfo->styles[1] != 255)
8611                                         {
8612                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8613                                                 lm += size3;
8614                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8615                                                 VectorMA(c, scale, lm, c);
8616                                                 if (surface->lightmapinfo->styles[2] != 255)
8617                                                 {
8618                                                         lm += size3;
8619                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8620                                                         VectorMA(c, scale, lm, c);
8621                                                         if (surface->lightmapinfo->styles[3] != 255)
8622                                                         {
8623                                                                 lm += size3;
8624                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8625                                                                 VectorMA(c, scale, lm, c);
8626                                                         }
8627                                                 }
8628                                         }
8629                                         c[0] >>= 7;
8630                                         c[1] >>= 7;
8631                                         c[2] >>= 7;
8632                                         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);
8633                                         numvertices++;
8634                                 }
8635                         }
8636                         else
8637                         {
8638                                 for (j = 0;j < surfacenumvertices;j++)
8639                                 {
8640                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8641                                         numvertices++;
8642                                 }
8643                         }
8644                 }
8645         }
8646
8647         // if vertices are deformed (sprite flares and things in maps, possibly
8648         // water waves, bulges and other deformations), modify the copied vertices
8649         // in place
8650         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8651         {
8652                 switch (deform->deform)
8653                 {
8654                 default:
8655                 case Q3DEFORM_PROJECTIONSHADOW:
8656                 case Q3DEFORM_TEXT0:
8657                 case Q3DEFORM_TEXT1:
8658                 case Q3DEFORM_TEXT2:
8659                 case Q3DEFORM_TEXT3:
8660                 case Q3DEFORM_TEXT4:
8661                 case Q3DEFORM_TEXT5:
8662                 case Q3DEFORM_TEXT6:
8663                 case Q3DEFORM_TEXT7:
8664                 case Q3DEFORM_NONE:
8665                         break;
8666                 case Q3DEFORM_AUTOSPRITE:
8667                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8668                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8670                         VectorNormalize(newforward);
8671                         VectorNormalize(newright);
8672                         VectorNormalize(newup);
8673 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8674 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8675 //                      rsurface.batchvertex3f_bufferoffset = 0;
8676 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8677 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8678 //                      rsurface.batchsvector3f_bufferoffset = 0;
8679 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8680 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8681 //                      rsurface.batchtvector3f_bufferoffset = 0;
8682 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8684 //                      rsurface.batchnormal3f_bufferoffset = 0;
8685                         // a single autosprite surface can contain multiple sprites...
8686                         for (j = 0;j < batchnumvertices - 3;j += 4)
8687                         {
8688                                 VectorClear(center);
8689                                 for (i = 0;i < 4;i++)
8690                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8691                                 VectorScale(center, 0.25f, center);
8692                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8693                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8694                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8695                                 for (i = 0;i < 4;i++)
8696                                 {
8697                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8698                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8699                                 }
8700                         }
8701                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8702                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8703                         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);
8704                         break;
8705                 case Q3DEFORM_AUTOSPRITE2:
8706                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8707                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8709                         VectorNormalize(newforward);
8710                         VectorNormalize(newright);
8711                         VectorNormalize(newup);
8712 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8713 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8714 //                      rsurface.batchvertex3f_bufferoffset = 0;
8715                         {
8716                                 const float *v1, *v2;
8717                                 vec3_t start, end;
8718                                 float f, l;
8719                                 struct
8720                                 {
8721                                         float length2;
8722                                         const float *v1;
8723                                         const float *v2;
8724                                 }
8725                                 shortest[2];
8726                                 memset(shortest, 0, sizeof(shortest));
8727                                 // a single autosprite surface can contain multiple sprites...
8728                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8729                                 {
8730                                         VectorClear(center);
8731                                         for (i = 0;i < 4;i++)
8732                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8733                                         VectorScale(center, 0.25f, center);
8734                                         // find the two shortest edges, then use them to define the
8735                                         // axis vectors for rotating around the central axis
8736                                         for (i = 0;i < 6;i++)
8737                                         {
8738                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8739                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8740                                                 l = VectorDistance2(v1, v2);
8741                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8742                                                 if (v1[2] != v2[2])
8743                                                         l += (1.0f / 1024.0f);
8744                                                 if (shortest[0].length2 > l || i == 0)
8745                                                 {
8746                                                         shortest[1] = shortest[0];
8747                                                         shortest[0].length2 = l;
8748                                                         shortest[0].v1 = v1;
8749                                                         shortest[0].v2 = v2;
8750                                                 }
8751                                                 else if (shortest[1].length2 > l || i == 1)
8752                                                 {
8753                                                         shortest[1].length2 = l;
8754                                                         shortest[1].v1 = v1;
8755                                                         shortest[1].v2 = v2;
8756                                                 }
8757                                         }
8758                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8759                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8760                                         // this calculates the right vector from the shortest edge
8761                                         // and the up vector from the edge midpoints
8762                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8763                                         VectorNormalize(right);
8764                                         VectorSubtract(end, start, up);
8765                                         VectorNormalize(up);
8766                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8767                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8768                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8769                                         VectorNegate(forward, forward);
8770                                         VectorReflect(forward, 0, up, forward);
8771                                         VectorNormalize(forward);
8772                                         CrossProduct(up, forward, newright);
8773                                         VectorNormalize(newright);
8774                                         // rotate the quad around the up axis vector, this is made
8775                                         // especially easy by the fact we know the quad is flat,
8776                                         // so we only have to subtract the center position and
8777                                         // measure distance along the right vector, and then
8778                                         // multiply that by the newright vector and add back the
8779                                         // center position
8780                                         // we also need to subtract the old position to undo the
8781                                         // displacement from the center, which we do with a
8782                                         // DotProduct, the subtraction/addition of center is also
8783                                         // optimized into DotProducts here
8784                                         l = DotProduct(right, center);
8785                                         for (i = 0;i < 4;i++)
8786                                         {
8787                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8788                                                 f = DotProduct(right, v1) - l;
8789                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8790                                         }
8791                                 }
8792                         }
8793                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8794                         {
8795 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8797 //                              rsurface.batchnormal3f_bufferoffset = 0;
8798                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8799                         }
8800                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8801                         {
8802 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8804 //                              rsurface.batchsvector3f_bufferoffset = 0;
8805 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8806 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8807 //                              rsurface.batchtvector3f_bufferoffset = 0;
8808                                 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);
8809                         }
8810                         break;
8811                 case Q3DEFORM_NORMAL:
8812                         // deform the normals to make reflections wavey
8813                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8814                         rsurface.batchnormal3f_vertexbuffer = NULL;
8815                         rsurface.batchnormal3f_bufferoffset = 0;
8816                         for (j = 0;j < batchnumvertices;j++)
8817                         {
8818                                 float vertex[3];
8819                                 float *normal = rsurface.batchnormal3f + 3*j;
8820                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8821                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8822                                 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]);
8823                                 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]);
8824                                 VectorNormalize(normal);
8825                         }
8826                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8827                         {
8828 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8829 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8830 //                              rsurface.batchsvector3f_bufferoffset = 0;
8831 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8832 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8833 //                              rsurface.batchtvector3f_bufferoffset = 0;
8834                                 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);
8835                         }
8836                         break;
8837                 case Q3DEFORM_WAVE:
8838                         // deform vertex array to make wavey water and flags and such
8839                         waveparms[0] = deform->waveparms[0];
8840                         waveparms[1] = deform->waveparms[1];
8841                         waveparms[2] = deform->waveparms[2];
8842                         waveparms[3] = deform->waveparms[3];
8843                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8844                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8845                         // this is how a divisor of vertex influence on deformation
8846                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8847                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8848 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8849 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8850 //                      rsurface.batchvertex3f_bufferoffset = 0;
8851 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8852 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8853 //                      rsurface.batchnormal3f_bufferoffset = 0;
8854                         for (j = 0;j < batchnumvertices;j++)
8855                         {
8856                                 // if the wavefunc depends on time, evaluate it per-vertex
8857                                 if (waveparms[3])
8858                                 {
8859                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8860                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8861                                 }
8862                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8863                         }
8864                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8865                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8866                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8867                         {
8868 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8869 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8870 //                              rsurface.batchsvector3f_bufferoffset = 0;
8871 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8873 //                              rsurface.batchtvector3f_bufferoffset = 0;
8874                                 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);
8875                         }
8876                         break;
8877                 case Q3DEFORM_BULGE:
8878                         // deform vertex array to make the surface have moving bulges
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                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8888                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8889                         }
8890                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8891                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8892                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8893                         {
8894 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8895 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8896 //                              rsurface.batchsvector3f_bufferoffset = 0;
8897 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8898 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8899 //                              rsurface.batchtvector3f_bufferoffset = 0;
8900                                 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);
8901                         }
8902                         break;
8903                 case Q3DEFORM_MOVE:
8904                         // deform vertex array
8905                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8906                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8907                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8908                         VectorScale(deform->parms, scale, waveparms);
8909 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8910 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8911 //                      rsurface.batchvertex3f_bufferoffset = 0;
8912                         for (j = 0;j < batchnumvertices;j++)
8913                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8914                         break;
8915                 }
8916         }
8917
8918         // generate texcoords based on the chosen texcoord source
8919         switch(rsurface.texture->tcgen.tcgen)
8920         {
8921         default:
8922         case Q3TCGEN_TEXTURE:
8923                 break;
8924         case Q3TCGEN_LIGHTMAP:
8925 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8926 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8927 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8928                 if (rsurface.batchtexcoordlightmap2f)
8929                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8930                 break;
8931         case Q3TCGEN_VECTOR:
8932 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8933 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8934 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8935                 for (j = 0;j < batchnumvertices;j++)
8936                 {
8937                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8938                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8939                 }
8940                 break;
8941         case Q3TCGEN_ENVIRONMENT:
8942                 // make environment reflections using a spheremap
8943                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8944                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8945                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8946                 for (j = 0;j < batchnumvertices;j++)
8947                 {
8948                         // identical to Q3A's method, but executed in worldspace so
8949                         // carried models can be shiny too
8950
8951                         float viewer[3], d, reflected[3], worldreflected[3];
8952
8953                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8954                         // VectorNormalize(viewer);
8955
8956                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8957
8958                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8959                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8960                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8961                         // note: this is proportinal to viewer, so we can normalize later
8962
8963                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8964                         VectorNormalize(worldreflected);
8965
8966                         // note: this sphere map only uses world x and z!
8967                         // so positive and negative y will LOOK THE SAME.
8968                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8969                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8970                 }
8971                 break;
8972         }
8973         // the only tcmod that needs software vertex processing is turbulent, so
8974         // check for it here and apply the changes if needed
8975         // and we only support that as the first one
8976         // (handling a mixture of turbulent and other tcmods would be problematic
8977         //  without punting it entirely to a software path)
8978         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8979         {
8980                 amplitude = rsurface.texture->tcmods[0].parms[1];
8981                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8982 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8983 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8984 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8985                 for (j = 0;j < batchnumvertices;j++)
8986                 {
8987                         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);
8988                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8989                 }
8990         }
8991
8992         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8993         {
8994                 // convert the modified arrays to vertex structs
8995 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8996 //              rsurface.batchvertexmeshbuffer = NULL;
8997                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8998                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8999                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9000                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9001                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9002                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9003                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9004                 {
9005                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9006                         {
9007                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9008                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9009                         }
9010                 }
9011                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9012                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9013                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9014                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9015                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9016                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9017                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9018                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9019                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9020         }
9021 }
9022
9023 void RSurf_DrawBatch(void)
9024 {
9025         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9026         // through the pipeline, killing it earlier in the pipeline would have
9027         // per-surface overhead rather than per-batch overhead, so it's best to
9028         // reject it here, before it hits glDraw.
9029         if (rsurface.batchnumtriangles == 0)
9030                 return;
9031 #if 0
9032         // batch debugging code
9033         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9034         {
9035                 int i;
9036                 int j;
9037                 int c;
9038                 const int *e;
9039                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9040                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9041                 {
9042                         c = e[i];
9043                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9044                         {
9045                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9046                                 {
9047                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9048                                                 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);
9049                                         break;
9050                                 }
9051                         }
9052                 }
9053         }
9054 #endif
9055         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);
9056 }
9057
9058 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9059 {
9060         // pick the closest matching water plane
9061         int planeindex, vertexindex, bestplaneindex = -1;
9062         float d, bestd;
9063         vec3_t vert;
9064         const float *v;
9065         r_waterstate_waterplane_t *p;
9066         qboolean prepared = false;
9067         bestd = 0;
9068         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9069         {
9070                 if(p->camera_entity != rsurface.texture->camera_entity)
9071                         continue;
9072                 d = 0;
9073                 if(!prepared)
9074                 {
9075                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9076                         prepared = true;
9077                         if(rsurface.batchnumvertices == 0)
9078                                 break;
9079                 }
9080                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9081                 {
9082                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9083                         d += fabs(PlaneDiff(vert, &p->plane));
9084                 }
9085                 if (bestd > d || bestplaneindex < 0)
9086                 {
9087                         bestd = d;
9088                         bestplaneindex = planeindex;
9089                 }
9090         }
9091         return bestplaneindex;
9092         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9093         // this situation though, as it might be better to render single larger
9094         // batches with useless stuff (backface culled for example) than to
9095         // render multiple smaller batches
9096 }
9097
9098 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9099 {
9100         int i;
9101         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9102         rsurface.passcolor4f_vertexbuffer = 0;
9103         rsurface.passcolor4f_bufferoffset = 0;
9104         for (i = 0;i < rsurface.batchnumvertices;i++)
9105                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9106 }
9107
9108 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9109 {
9110         int i;
9111         float f;
9112         const float *v;
9113         const float *c;
9114         float *c2;
9115         if (rsurface.passcolor4f)
9116         {
9117                 // generate color arrays
9118                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9119                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9120                 rsurface.passcolor4f_vertexbuffer = 0;
9121                 rsurface.passcolor4f_bufferoffset = 0;
9122                 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)
9123                 {
9124                         f = RSurf_FogVertex(v);
9125                         c2[0] = c[0] * f;
9126                         c2[1] = c[1] * f;
9127                         c2[2] = c[2] * f;
9128                         c2[3] = c[3];
9129                 }
9130         }
9131         else
9132         {
9133                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9134                 rsurface.passcolor4f_vertexbuffer = 0;
9135                 rsurface.passcolor4f_bufferoffset = 0;
9136                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9137                 {
9138                         f = RSurf_FogVertex(v);
9139                         c2[0] = f;
9140                         c2[1] = f;
9141                         c2[2] = f;
9142                         c2[3] = 1;
9143                 }
9144         }
9145 }
9146
9147 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9148 {
9149         int i;
9150         float f;
9151         const float *v;
9152         const float *c;
9153         float *c2;
9154         if (!rsurface.passcolor4f)
9155                 return;
9156         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9157         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9158         rsurface.passcolor4f_vertexbuffer = 0;
9159         rsurface.passcolor4f_bufferoffset = 0;
9160         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)
9161         {
9162                 f = RSurf_FogVertex(v);
9163                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9164                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9165                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9166                 c2[3] = c[3];
9167         }
9168 }
9169
9170 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9171 {
9172         int i;
9173         const float *c;
9174         float *c2;
9175         if (!rsurface.passcolor4f)
9176                 return;
9177         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9178         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9179         rsurface.passcolor4f_vertexbuffer = 0;
9180         rsurface.passcolor4f_bufferoffset = 0;
9181         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9182         {
9183                 c2[0] = c[0] * r;
9184                 c2[1] = c[1] * g;
9185                 c2[2] = c[2] * b;
9186                 c2[3] = c[3] * a;
9187         }
9188 }
9189
9190 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9191 {
9192         int i;
9193         const float *c;
9194         float *c2;
9195         if (!rsurface.passcolor4f)
9196                 return;
9197         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9198         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9199         rsurface.passcolor4f_vertexbuffer = 0;
9200         rsurface.passcolor4f_bufferoffset = 0;
9201         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9202         {
9203                 c2[0] = c[0] + r_refdef.scene.ambient;
9204                 c2[1] = c[1] + r_refdef.scene.ambient;
9205                 c2[2] = c[2] + r_refdef.scene.ambient;
9206                 c2[3] = c[3];
9207         }
9208 }
9209
9210 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9211 {
9212         // TODO: optimize
9213         rsurface.passcolor4f = NULL;
9214         rsurface.passcolor4f_vertexbuffer = 0;
9215         rsurface.passcolor4f_bufferoffset = 0;
9216         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9217         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9218         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9219         GL_Color(r, g, b, a);
9220         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9221         RSurf_DrawBatch();
9222 }
9223
9224 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9225 {
9226         // TODO: optimize applyfog && applycolor case
9227         // just apply fog if necessary, and tint the fog color array if necessary
9228         rsurface.passcolor4f = NULL;
9229         rsurface.passcolor4f_vertexbuffer = 0;
9230         rsurface.passcolor4f_bufferoffset = 0;
9231         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9232         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9233         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9234         GL_Color(r, g, b, a);
9235         RSurf_DrawBatch();
9236 }
9237
9238 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9239 {
9240         // TODO: optimize
9241         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9242         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9243         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9244         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9245         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9246         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9247         GL_Color(r, g, b, a);
9248         RSurf_DrawBatch();
9249 }
9250
9251 static void RSurf_DrawBatch_GL11_ClampColor(void)
9252 {
9253         int i;
9254         const float *c1;
9255         float *c2;
9256         if (!rsurface.passcolor4f)
9257                 return;
9258         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9259         {
9260                 c2[0] = bound(0.0f, c1[0], 1.0f);
9261                 c2[1] = bound(0.0f, c1[1], 1.0f);
9262                 c2[2] = bound(0.0f, c1[2], 1.0f);
9263                 c2[3] = bound(0.0f, c1[3], 1.0f);
9264         }
9265 }
9266
9267 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9268 {
9269         int i;
9270         float f;
9271         const float *v;
9272         const float *n;
9273         float *c;
9274         //vec3_t eyedir;
9275
9276         // fake shading
9277         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9278         rsurface.passcolor4f_vertexbuffer = 0;
9279         rsurface.passcolor4f_bufferoffset = 0;
9280         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)
9281         {
9282                 f = -DotProduct(r_refdef.view.forward, n);
9283                 f = max(0, f);
9284                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9285                 f *= r_refdef.lightmapintensity;
9286                 Vector4Set(c, f, f, f, 1);
9287         }
9288 }
9289
9290 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9291 {
9292         RSurf_DrawBatch_GL11_ApplyFakeLight();
9293         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9294         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9295         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9296         GL_Color(r, g, b, a);
9297         RSurf_DrawBatch();
9298 }
9299
9300 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9301 {
9302         int i;
9303         float f;
9304         float alpha;
9305         const float *v;
9306         const float *n;
9307         float *c;
9308         vec3_t ambientcolor;
9309         vec3_t diffusecolor;
9310         vec3_t lightdir;
9311         // TODO: optimize
9312         // model lighting
9313         VectorCopy(rsurface.modellight_lightdir, lightdir);
9314         f = 0.5f * r_refdef.lightmapintensity;
9315         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9316         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9317         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9318         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9319         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9320         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9321         alpha = *a;
9322         if (VectorLength2(diffusecolor) > 0)
9323         {
9324                 // q3-style directional shading
9325                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9326                 rsurface.passcolor4f_vertexbuffer = 0;
9327                 rsurface.passcolor4f_bufferoffset = 0;
9328                 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)
9329                 {
9330                         if ((f = DotProduct(n, lightdir)) > 0)
9331                                 VectorMA(ambientcolor, f, diffusecolor, c);
9332                         else
9333                                 VectorCopy(ambientcolor, c);
9334                         c[3] = alpha;
9335                 }
9336                 *r = 1;
9337                 *g = 1;
9338                 *b = 1;
9339                 *a = 1;
9340                 *applycolor = false;
9341         }
9342         else
9343         {
9344                 *r = ambientcolor[0];
9345                 *g = ambientcolor[1];
9346                 *b = ambientcolor[2];
9347                 rsurface.passcolor4f = NULL;
9348                 rsurface.passcolor4f_vertexbuffer = 0;
9349                 rsurface.passcolor4f_bufferoffset = 0;
9350         }
9351 }
9352
9353 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9354 {
9355         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9356         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9357         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9358         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9359         GL_Color(r, g, b, a);
9360         RSurf_DrawBatch();
9361 }
9362
9363 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9364 {
9365         int i;
9366         float f;
9367         const float *v;
9368         float *c;
9369
9370         // fake shading
9371         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9372         rsurface.passcolor4f_vertexbuffer = 0;
9373         rsurface.passcolor4f_bufferoffset = 0;
9374
9375         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9376         {
9377                 f = 1 - RSurf_FogVertex(v);
9378                 c[0] = r;
9379                 c[1] = g;
9380                 c[2] = b;
9381                 c[3] = f * a;
9382         }
9383 }
9384
9385 void RSurf_SetupDepthAndCulling(void)
9386 {
9387         // submodels are biased to avoid z-fighting with world surfaces that they
9388         // may be exactly overlapping (avoids z-fighting artifacts on certain
9389         // doors and things in Quake maps)
9390         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9391         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9392         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9393         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9394 }
9395
9396 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9397 {
9398         // transparent sky would be ridiculous
9399         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9400                 return;
9401         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9402         skyrenderlater = true;
9403         RSurf_SetupDepthAndCulling();
9404         GL_DepthMask(true);
9405         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9406         // skymasking on them, and Quake3 never did sky masking (unlike
9407         // software Quake and software Quake2), so disable the sky masking
9408         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9409         // and skymasking also looks very bad when noclipping outside the
9410         // level, so don't use it then either.
9411         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9412         {
9413                 R_Mesh_ResetTextureState();
9414                 if (skyrendermasked)
9415                 {
9416                         R_SetupShader_DepthOrShadow();
9417                         // depth-only (masking)
9418                         GL_ColorMask(0,0,0,0);
9419                         // just to make sure that braindead drivers don't draw
9420                         // anything despite that colormask...
9421                         GL_BlendFunc(GL_ZERO, GL_ONE);
9422                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9423                         if (rsurface.batchvertex3fbuffer)
9424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9425                         else
9426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9427                 }
9428                 else
9429                 {
9430                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9431                         // fog sky
9432                         GL_BlendFunc(GL_ONE, GL_ZERO);
9433                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9434                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9435                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9436                 }
9437                 RSurf_DrawBatch();
9438                 if (skyrendermasked)
9439                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9440         }
9441         R_Mesh_ResetTextureState();
9442         GL_Color(1, 1, 1, 1);
9443 }
9444
9445 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9446 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9447 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9448 {
9449         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9450                 return;
9451         if (prepass)
9452         {
9453                 // render screenspace normalmap to texture
9454                 GL_DepthMask(true);
9455                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9456                 RSurf_DrawBatch();
9457                 return;
9458         }
9459
9460         // bind lightmap texture
9461
9462         // water/refraction/reflection/camera surfaces have to be handled specially
9463         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9464         {
9465                 int start, end, startplaneindex;
9466                 for (start = 0;start < texturenumsurfaces;start = end)
9467                 {
9468                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9469                         if(startplaneindex < 0)
9470                         {
9471                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9472                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9473                                 end = start + 1;
9474                                 continue;
9475                         }
9476                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9477                                 ;
9478                         // now that we have a batch using the same planeindex, render it
9479                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9480                         {
9481                                 // render water or distortion background
9482                                 GL_DepthMask(true);
9483                                 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));
9484                                 RSurf_DrawBatch();
9485                                 // blend surface on top
9486                                 GL_DepthMask(false);
9487                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9488                                 RSurf_DrawBatch();
9489                         }
9490                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9491                         {
9492                                 // render surface with reflection texture as input
9493                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9494                                 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));
9495                                 RSurf_DrawBatch();
9496                         }
9497                 }
9498                 return;
9499         }
9500
9501         // render surface batch normally
9502         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9503         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9504         RSurf_DrawBatch();
9505 }
9506
9507 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9508 {
9509         // OpenGL 1.3 path - anything not completely ancient
9510         qboolean applycolor;
9511         qboolean applyfog;
9512         int layerindex;
9513         const texturelayer_t *layer;
9514         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);
9515         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9516
9517         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9518         {
9519                 vec4_t layercolor;
9520                 int layertexrgbscale;
9521                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9522                 {
9523                         if (layerindex == 0)
9524                                 GL_AlphaTest(true);
9525                         else
9526                         {
9527                                 GL_AlphaTest(false);
9528                                 GL_DepthFunc(GL_EQUAL);
9529                         }
9530                 }
9531                 GL_DepthMask(layer->depthmask && writedepth);
9532                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9533                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9534                 {
9535                         layertexrgbscale = 4;
9536                         VectorScale(layer->color, 0.25f, layercolor);
9537                 }
9538                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9539                 {
9540                         layertexrgbscale = 2;
9541                         VectorScale(layer->color, 0.5f, layercolor);
9542                 }
9543                 else
9544                 {
9545                         layertexrgbscale = 1;
9546                         VectorScale(layer->color, 1.0f, layercolor);
9547                 }
9548                 layercolor[3] = layer->color[3];
9549                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9550                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9551                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9552                 switch (layer->type)
9553                 {
9554                 case TEXTURELAYERTYPE_LITTEXTURE:
9555                         // single-pass lightmapped texture with 2x rgbscale
9556                         R_Mesh_TexBind(0, r_texture_white);
9557                         R_Mesh_TexMatrix(0, NULL);
9558                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9559                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9560                         R_Mesh_TexBind(1, layer->texture);
9561                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9562                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9563                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9564                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9565                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9566                         else if (FAKELIGHT_ENABLED)
9567                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9568                         else if (rsurface.uselightmaptexture)
9569                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9570                         else
9571                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9572                         break;
9573                 case TEXTURELAYERTYPE_TEXTURE:
9574                         // singletexture unlit texture with transparency support
9575                         R_Mesh_TexBind(0, layer->texture);
9576                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9577                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9578                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9579                         R_Mesh_TexBind(1, 0);
9580                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9581                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9582                         break;
9583                 case TEXTURELAYERTYPE_FOG:
9584                         // singletexture fogging
9585                         if (layer->texture)
9586                         {
9587                                 R_Mesh_TexBind(0, layer->texture);
9588                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9589                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9590                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9591                         }
9592                         else
9593                         {
9594                                 R_Mesh_TexBind(0, 0);
9595                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9596                         }
9597                         R_Mesh_TexBind(1, 0);
9598                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9599                         // generate a color array for the fog pass
9600                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9601                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9602                         RSurf_DrawBatch();
9603                         break;
9604                 default:
9605                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9606                 }
9607         }
9608         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9609         {
9610                 GL_DepthFunc(GL_LEQUAL);
9611                 GL_AlphaTest(false);
9612         }
9613 }
9614
9615 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9616 {
9617         // OpenGL 1.1 - crusty old voodoo path
9618         qboolean applyfog;
9619         int layerindex;
9620         const texturelayer_t *layer;
9621         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);
9622         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9623
9624         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9625         {
9626                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9627                 {
9628                         if (layerindex == 0)
9629                                 GL_AlphaTest(true);
9630                         else
9631                         {
9632                                 GL_AlphaTest(false);
9633                                 GL_DepthFunc(GL_EQUAL);
9634                         }
9635                 }
9636                 GL_DepthMask(layer->depthmask && writedepth);
9637                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9638                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9639                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9640                 switch (layer->type)
9641                 {
9642                 case TEXTURELAYERTYPE_LITTEXTURE:
9643                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9644                         {
9645                                 // two-pass lit texture with 2x rgbscale
9646                                 // first the lightmap pass
9647                                 R_Mesh_TexBind(0, r_texture_white);
9648                                 R_Mesh_TexMatrix(0, NULL);
9649                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9650                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9651                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9652                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9653                                 else if (FAKELIGHT_ENABLED)
9654                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9655                                 else if (rsurface.uselightmaptexture)
9656                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9657                                 else
9658                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9659                                 // then apply the texture to it
9660                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9661                                 R_Mesh_TexBind(0, layer->texture);
9662                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9663                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9664                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9665                                 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);
9666                         }
9667                         else
9668                         {
9669                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9670                                 R_Mesh_TexBind(0, layer->texture);
9671                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9672                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9673                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9674                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9675                                         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);
9676                                 else
9677                                         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);
9678                         }
9679                         break;
9680                 case TEXTURELAYERTYPE_TEXTURE:
9681                         // singletexture unlit texture with transparency support
9682                         R_Mesh_TexBind(0, layer->texture);
9683                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9684                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9685                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9686                         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);
9687                         break;
9688                 case TEXTURELAYERTYPE_FOG:
9689                         // singletexture fogging
9690                         if (layer->texture)
9691                         {
9692                                 R_Mesh_TexBind(0, layer->texture);
9693                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9694                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9695                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9696                         }
9697                         else
9698                         {
9699                                 R_Mesh_TexBind(0, 0);
9700                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9701                         }
9702                         // generate a color array for the fog pass
9703                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9704                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9705                         RSurf_DrawBatch();
9706                         break;
9707                 default:
9708                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9709                 }
9710         }
9711         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9712         {
9713                 GL_DepthFunc(GL_LEQUAL);
9714                 GL_AlphaTest(false);
9715         }
9716 }
9717
9718 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9719 {
9720         int vi;
9721         int j;
9722         r_vertexgeneric_t *batchvertex;
9723         float c[4];
9724
9725 //      R_Mesh_ResetTextureState();
9726         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9727
9728         if(rsurface.texture && rsurface.texture->currentskinframe)
9729         {
9730                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9731                 c[3] *= rsurface.texture->currentalpha;
9732         }
9733         else
9734         {
9735                 c[0] = 1;
9736                 c[1] = 0;
9737                 c[2] = 1;
9738                 c[3] = 1;
9739         }
9740
9741         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9742         {
9743                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9744                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9745                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9746         }
9747
9748         // brighten it up (as texture value 127 means "unlit")
9749         c[0] *= 2 * r_refdef.view.colorscale;
9750         c[1] *= 2 * r_refdef.view.colorscale;
9751         c[2] *= 2 * r_refdef.view.colorscale;
9752
9753         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9754                 c[3] *= r_wateralpha.value;
9755
9756         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9757         {
9758                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9759                 GL_DepthMask(false);
9760         }
9761         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9762         {
9763                 GL_BlendFunc(GL_ONE, GL_ONE);
9764                 GL_DepthMask(false);
9765         }
9766         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9767         {
9768                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9769                 GL_DepthMask(false);
9770         }
9771         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9772         {
9773                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9774                 GL_DepthMask(false);
9775         }
9776         else
9777         {
9778                 GL_BlendFunc(GL_ONE, GL_ZERO);
9779                 GL_DepthMask(writedepth);
9780         }
9781
9782         if (r_showsurfaces.integer == 3)
9783         {
9784                 rsurface.passcolor4f = NULL;
9785
9786                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9787                 {
9788                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9789
9790                         rsurface.passcolor4f = NULL;
9791                         rsurface.passcolor4f_vertexbuffer = 0;
9792                         rsurface.passcolor4f_bufferoffset = 0;
9793                 }
9794                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9795                 {
9796                         qboolean applycolor = true;
9797                         float one = 1.0;
9798
9799                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9800
9801                         r_refdef.lightmapintensity = 1;
9802                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9803                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9804                 }
9805                 else if (FAKELIGHT_ENABLED)
9806                 {
9807                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808
9809                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9810                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9811                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9812                 }
9813                 else
9814                 {
9815                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816
9817                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9818                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9819                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9820                 }
9821
9822                 if(!rsurface.passcolor4f)
9823                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9824
9825                 RSurf_DrawBatch_GL11_ApplyAmbient();
9826                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9827                 if(r_refdef.fogenabled)
9828                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9829                 RSurf_DrawBatch_GL11_ClampColor();
9830
9831                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9832                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9833                 RSurf_DrawBatch();
9834         }
9835         else if (!r_refdef.view.showdebug)
9836         {
9837                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9838                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9839                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9840                 {
9841                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9842                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9843                 }
9844                 R_Mesh_PrepareVertices_Generic_Unlock();
9845                 RSurf_DrawBatch();
9846         }
9847         else if (r_showsurfaces.integer == 4)
9848         {
9849                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9850                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9851                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9852                 {
9853                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9854                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9855                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9856                 }
9857                 R_Mesh_PrepareVertices_Generic_Unlock();
9858                 RSurf_DrawBatch();
9859         }
9860         else if (r_showsurfaces.integer == 2)
9861         {
9862                 const int *e;
9863                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9864                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9865                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9866                 {
9867                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9868                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9869                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9870                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9871                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9872                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9873                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9874                 }
9875                 R_Mesh_PrepareVertices_Generic_Unlock();
9876                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9877         }
9878         else
9879         {
9880                 int texturesurfaceindex;
9881                 int k;
9882                 const msurface_t *surface;
9883                 float surfacecolor4f[4];
9884                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9885                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9886                 vi = 0;
9887                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9888                 {
9889                         surface = texturesurfacelist[texturesurfaceindex];
9890                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9891                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9892                         for (j = 0;j < surface->num_vertices;j++)
9893                         {
9894                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9895                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9896                                 vi++;
9897                         }
9898                 }
9899                 R_Mesh_PrepareVertices_Generic_Unlock();
9900                 RSurf_DrawBatch();
9901         }
9902 }
9903
9904 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9905 {
9906         CHECKGLERROR
9907         RSurf_SetupDepthAndCulling();
9908         if (r_showsurfaces.integer)
9909         {
9910                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9911                 return;
9912         }
9913         switch (vid.renderpath)
9914         {
9915         case RENDERPATH_GL20:
9916         case RENDERPATH_D3D9:
9917         case RENDERPATH_D3D10:
9918         case RENDERPATH_D3D11:
9919         case RENDERPATH_SOFT:
9920         case RENDERPATH_GLES2:
9921                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9922                 break;
9923         case RENDERPATH_GL13:
9924         case RENDERPATH_GLES1:
9925                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9926                 break;
9927         case RENDERPATH_GL11:
9928                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9929                 break;
9930         }
9931         CHECKGLERROR
9932 }
9933
9934 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9935 {
9936         CHECKGLERROR
9937         RSurf_SetupDepthAndCulling();
9938         if (r_showsurfaces.integer)
9939         {
9940                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9941                 return;
9942         }
9943         switch (vid.renderpath)
9944         {
9945         case RENDERPATH_GL20:
9946         case RENDERPATH_D3D9:
9947         case RENDERPATH_D3D10:
9948         case RENDERPATH_D3D11:
9949         case RENDERPATH_SOFT:
9950         case RENDERPATH_GLES2:
9951                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9952                 break;
9953         case RENDERPATH_GL13:
9954         case RENDERPATH_GLES1:
9955                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9956                 break;
9957         case RENDERPATH_GL11:
9958                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9959                 break;
9960         }
9961         CHECKGLERROR
9962 }
9963
9964 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9965 {
9966         int i, j;
9967         int texturenumsurfaces, endsurface;
9968         texture_t *texture;
9969         const msurface_t *surface;
9970         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9971
9972         // if the model is static it doesn't matter what value we give for
9973         // wantnormals and wanttangents, so this logic uses only rules applicable
9974         // to a model, knowing that they are meaningless otherwise
9975         if (ent == r_refdef.scene.worldentity)
9976                 RSurf_ActiveWorldEntity();
9977         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9978                 RSurf_ActiveModelEntity(ent, false, false, false);
9979         else
9980         {
9981                 switch (vid.renderpath)
9982                 {
9983                 case RENDERPATH_GL20:
9984                 case RENDERPATH_D3D9:
9985                 case RENDERPATH_D3D10:
9986                 case RENDERPATH_D3D11:
9987                 case RENDERPATH_SOFT:
9988                 case RENDERPATH_GLES2:
9989                         RSurf_ActiveModelEntity(ent, true, true, false);
9990                         break;
9991                 case RENDERPATH_GL11:
9992                 case RENDERPATH_GL13:
9993                 case RENDERPATH_GLES1:
9994                         RSurf_ActiveModelEntity(ent, true, false, false);
9995                         break;
9996                 }
9997         }
9998
9999         if (r_transparentdepthmasking.integer)
10000         {
10001                 qboolean setup = false;
10002                 for (i = 0;i < numsurfaces;i = j)
10003                 {
10004                         j = i + 1;
10005                         surface = rsurface.modelsurfaces + surfacelist[i];
10006                         texture = surface->texture;
10007                         rsurface.texture = R_GetCurrentTexture(texture);
10008                         rsurface.lightmaptexture = NULL;
10009                         rsurface.deluxemaptexture = NULL;
10010                         rsurface.uselightmaptexture = false;
10011                         // scan ahead until we find a different texture
10012                         endsurface = min(i + 1024, numsurfaces);
10013                         texturenumsurfaces = 0;
10014                         texturesurfacelist[texturenumsurfaces++] = surface;
10015                         for (;j < endsurface;j++)
10016                         {
10017                                 surface = rsurface.modelsurfaces + surfacelist[j];
10018                                 if (texture != surface->texture)
10019                                         break;
10020                                 texturesurfacelist[texturenumsurfaces++] = surface;
10021                         }
10022                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10023                                 continue;
10024                         // render the range of surfaces as depth
10025                         if (!setup)
10026                         {
10027                                 setup = true;
10028                                 GL_ColorMask(0,0,0,0);
10029                                 GL_Color(1,1,1,1);
10030                                 GL_DepthTest(true);
10031                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10032                                 GL_DepthMask(true);
10033 //                              R_Mesh_ResetTextureState();
10034                                 R_SetupShader_DepthOrShadow();
10035                         }
10036                         RSurf_SetupDepthAndCulling();
10037                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10038                         if (rsurface.batchvertex3fbuffer)
10039                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10040                         else
10041                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10042                         RSurf_DrawBatch();
10043                 }
10044                 if (setup)
10045                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10046         }
10047
10048         for (i = 0;i < numsurfaces;i = j)
10049         {
10050                 j = i + 1;
10051                 surface = rsurface.modelsurfaces + surfacelist[i];
10052                 texture = surface->texture;
10053                 rsurface.texture = R_GetCurrentTexture(texture);
10054                 // scan ahead until we find a different texture
10055                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10056                 texturenumsurfaces = 0;
10057                 texturesurfacelist[texturenumsurfaces++] = surface;
10058                 if(FAKELIGHT_ENABLED)
10059                 {
10060                         rsurface.lightmaptexture = NULL;
10061                         rsurface.deluxemaptexture = NULL;
10062                         rsurface.uselightmaptexture = false;
10063                         for (;j < endsurface;j++)
10064                         {
10065                                 surface = rsurface.modelsurfaces + surfacelist[j];
10066                                 if (texture != surface->texture)
10067                                         break;
10068                                 texturesurfacelist[texturenumsurfaces++] = surface;
10069                         }
10070                 }
10071                 else
10072                 {
10073                         rsurface.lightmaptexture = surface->lightmaptexture;
10074                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10075                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10076                         for (;j < endsurface;j++)
10077                         {
10078                                 surface = rsurface.modelsurfaces + surfacelist[j];
10079                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10080                                         break;
10081                                 texturesurfacelist[texturenumsurfaces++] = surface;
10082                         }
10083                 }
10084                 // render the range of surfaces
10085                 if (ent == r_refdef.scene.worldentity)
10086                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10087                 else
10088                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10089         }
10090         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10091 }
10092
10093 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10094 {
10095         // transparent surfaces get pushed off into the transparent queue
10096         int surfacelistindex;
10097         const msurface_t *surface;
10098         vec3_t tempcenter, center;
10099         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10100         {
10101                 surface = texturesurfacelist[surfacelistindex];
10102                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10103                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10104                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10105                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10106                 if (queueentity->transparent_offset) // transparent offset
10107                 {
10108                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10109                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10110                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10111                 }
10112                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10113         }
10114 }
10115
10116 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10117 {
10118         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10119                 return;
10120         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10121                 return;
10122         RSurf_SetupDepthAndCulling();
10123         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10124         if (rsurface.batchvertex3fbuffer)
10125                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10126         else
10127                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10128         RSurf_DrawBatch();
10129 }
10130
10131 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10132 {
10133         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10134         CHECKGLERROR
10135         if (depthonly)
10136                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10137         else if (prepass)
10138         {
10139                 if (!rsurface.texture->currentnumlayers)
10140                         return;
10141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10142                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10143                 else
10144                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10145         }
10146         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10147                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10148         else if (!rsurface.texture->currentnumlayers)
10149                 return;
10150         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10151         {
10152                 // in the deferred case, transparent surfaces were queued during prepass
10153                 if (!r_shadow_usingdeferredprepass)
10154                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10155         }
10156         else
10157         {
10158                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10159                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10160         }
10161         CHECKGLERROR
10162 }
10163
10164 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10165 {
10166         int i, j;
10167         texture_t *texture;
10168         R_FrameData_SetMark();
10169         // break the surface list down into batches by texture and use of lightmapping
10170         for (i = 0;i < numsurfaces;i = j)
10171         {
10172                 j = i + 1;
10173                 // texture is the base texture pointer, rsurface.texture is the
10174                 // current frame/skin the texture is directing us to use (for example
10175                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10176                 // use skin 1 instead)
10177                 texture = surfacelist[i]->texture;
10178                 rsurface.texture = R_GetCurrentTexture(texture);
10179                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10180                 {
10181                         // if this texture is not the kind we want, skip ahead to the next one
10182                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10183                                 ;
10184                         continue;
10185                 }
10186                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10187                 {
10188                         rsurface.lightmaptexture = NULL;
10189                         rsurface.deluxemaptexture = NULL;
10190                         rsurface.uselightmaptexture = false;
10191                         // simply scan ahead until we find a different texture or lightmap state
10192                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10193                                 ;
10194                 }
10195                 else
10196                 {
10197                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10198                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10199                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10200                         // simply scan ahead until we find a different texture or lightmap state
10201                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10202                                 ;
10203                 }
10204                 // render the range of surfaces
10205                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10206         }
10207         R_FrameData_ReturnToMark();
10208 }
10209
10210 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10211 {
10212         CHECKGLERROR
10213         if (depthonly)
10214                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10215         else if (prepass)
10216         {
10217                 if (!rsurface.texture->currentnumlayers)
10218                         return;
10219                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10220                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10221                 else
10222                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10223         }
10224         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10225                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10226         else if (!rsurface.texture->currentnumlayers)
10227                 return;
10228         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10229         {
10230                 // in the deferred case, transparent surfaces were queued during prepass
10231                 if (!r_shadow_usingdeferredprepass)
10232                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10233         }
10234         else
10235         {
10236                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10237                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10238         }
10239         CHECKGLERROR
10240 }
10241
10242 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10243 {
10244         int i, j;
10245         texture_t *texture;
10246         R_FrameData_SetMark();
10247         // break the surface list down into batches by texture and use of lightmapping
10248         for (i = 0;i < numsurfaces;i = j)
10249         {
10250                 j = i + 1;
10251                 // texture is the base texture pointer, rsurface.texture is the
10252                 // current frame/skin the texture is directing us to use (for example
10253                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10254                 // use skin 1 instead)
10255                 texture = surfacelist[i]->texture;
10256                 rsurface.texture = R_GetCurrentTexture(texture);
10257                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10258                 {
10259                         // if this texture is not the kind we want, skip ahead to the next one
10260                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10261                                 ;
10262                         continue;
10263                 }
10264                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10265                 {
10266                         rsurface.lightmaptexture = NULL;
10267                         rsurface.deluxemaptexture = NULL;
10268                         rsurface.uselightmaptexture = false;
10269                         // simply scan ahead until we find a different texture or lightmap state
10270                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10271                                 ;
10272                 }
10273                 else
10274                 {
10275                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10276                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10277                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10278                         // simply scan ahead until we find a different texture or lightmap state
10279                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10280                                 ;
10281                 }
10282                 // render the range of surfaces
10283                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10284         }
10285         R_FrameData_ReturnToMark();
10286 }
10287
10288 float locboxvertex3f[6*4*3] =
10289 {
10290         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10291         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10292         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10293         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10294         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10295         1,0,0, 0,0,0, 0,1,0, 1,1,0
10296 };
10297
10298 unsigned short locboxelements[6*2*3] =
10299 {
10300          0, 1, 2, 0, 2, 3,
10301          4, 5, 6, 4, 6, 7,
10302          8, 9,10, 8,10,11,
10303         12,13,14, 12,14,15,
10304         16,17,18, 16,18,19,
10305         20,21,22, 20,22,23
10306 };
10307
10308 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10309 {
10310         int i, j;
10311         cl_locnode_t *loc = (cl_locnode_t *)ent;
10312         vec3_t mins, size;
10313         float vertex3f[6*4*3];
10314         CHECKGLERROR
10315         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10316         GL_DepthMask(false);
10317         GL_DepthRange(0, 1);
10318         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10319         GL_DepthTest(true);
10320         GL_CullFace(GL_NONE);
10321         R_EntityMatrix(&identitymatrix);
10322
10323 //      R_Mesh_ResetTextureState();
10324
10325         i = surfacelist[0];
10326         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10327                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10328                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10329                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10330
10331         if (VectorCompare(loc->mins, loc->maxs))
10332         {
10333                 VectorSet(size, 2, 2, 2);
10334                 VectorMA(loc->mins, -0.5f, size, mins);
10335         }
10336         else
10337         {
10338                 VectorCopy(loc->mins, mins);
10339                 VectorSubtract(loc->maxs, loc->mins, size);
10340         }
10341
10342         for (i = 0;i < 6*4*3;)
10343                 for (j = 0;j < 3;j++, i++)
10344                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10345
10346         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10347         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10348         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10349 }
10350
10351 void R_DrawLocs(void)
10352 {
10353         int index;
10354         cl_locnode_t *loc, *nearestloc;
10355         vec3_t center;
10356         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10357         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10358         {
10359                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10360                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10361         }
10362 }
10363
10364 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10365 {
10366         if (decalsystem->decals)
10367                 Mem_Free(decalsystem->decals);
10368         memset(decalsystem, 0, sizeof(*decalsystem));
10369 }
10370
10371 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)
10372 {
10373         tridecal_t *decal;
10374         tridecal_t *decals;
10375         int i;
10376
10377         // expand or initialize the system
10378         if (decalsystem->maxdecals <= decalsystem->numdecals)
10379         {
10380                 decalsystem_t old = *decalsystem;
10381                 qboolean useshortelements;
10382                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10383                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10384                 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)));
10385                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10386                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10387                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10388                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10389                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10390                 if (decalsystem->numdecals)
10391                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10392                 if (old.decals)
10393                         Mem_Free(old.decals);
10394                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10395                         decalsystem->element3i[i] = i;
10396                 if (useshortelements)
10397                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10398                                 decalsystem->element3s[i] = i;
10399         }
10400
10401         // grab a decal and search for another free slot for the next one
10402         decals = decalsystem->decals;
10403         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10404         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10405                 ;
10406         decalsystem->freedecal = i;
10407         if (decalsystem->numdecals <= i)
10408                 decalsystem->numdecals = i + 1;
10409
10410         // initialize the decal
10411         decal->lived = 0;
10412         decal->triangleindex = triangleindex;
10413         decal->surfaceindex = surfaceindex;
10414         decal->decalsequence = decalsequence;
10415         decal->color4f[0][0] = c0[0];
10416         decal->color4f[0][1] = c0[1];
10417         decal->color4f[0][2] = c0[2];
10418         decal->color4f[0][3] = 1;
10419         decal->color4f[1][0] = c1[0];
10420         decal->color4f[1][1] = c1[1];
10421         decal->color4f[1][2] = c1[2];
10422         decal->color4f[1][3] = 1;
10423         decal->color4f[2][0] = c2[0];
10424         decal->color4f[2][1] = c2[1];
10425         decal->color4f[2][2] = c2[2];
10426         decal->color4f[2][3] = 1;
10427         decal->vertex3f[0][0] = v0[0];
10428         decal->vertex3f[0][1] = v0[1];
10429         decal->vertex3f[0][2] = v0[2];
10430         decal->vertex3f[1][0] = v1[0];
10431         decal->vertex3f[1][1] = v1[1];
10432         decal->vertex3f[1][2] = v1[2];
10433         decal->vertex3f[2][0] = v2[0];
10434         decal->vertex3f[2][1] = v2[1];
10435         decal->vertex3f[2][2] = v2[2];
10436         decal->texcoord2f[0][0] = t0[0];
10437         decal->texcoord2f[0][1] = t0[1];
10438         decal->texcoord2f[1][0] = t1[0];
10439         decal->texcoord2f[1][1] = t1[1];
10440         decal->texcoord2f[2][0] = t2[0];
10441         decal->texcoord2f[2][1] = t2[1];
10442         TriangleNormal(v0, v1, v2, decal->plane);
10443         VectorNormalize(decal->plane);
10444         decal->plane[3] = DotProduct(v0, decal->plane);
10445 }
10446
10447 extern cvar_t cl_decals_bias;
10448 extern cvar_t cl_decals_models;
10449 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10450 // baseparms, parms, temps
10451 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)
10452 {
10453         int cornerindex;
10454         int index;
10455         float v[9][3];
10456         const float *vertex3f;
10457         const float *normal3f;
10458         int numpoints;
10459         float points[2][9][3];
10460         float temp[3];
10461         float tc[9][2];
10462         float f;
10463         float c[9][4];
10464         const int *e;
10465
10466         e = rsurface.modelelement3i + 3*triangleindex;
10467
10468         vertex3f = rsurface.modelvertex3f;
10469         normal3f = rsurface.modelnormal3f;
10470
10471         if (normal3f)
10472         {
10473                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10474                 {
10475                         index = 3*e[cornerindex];
10476                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10477                 }
10478         }
10479         else
10480         {
10481                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10482                 {
10483                         index = 3*e[cornerindex];
10484                         VectorCopy(vertex3f + index, v[cornerindex]);
10485                 }
10486         }
10487
10488         // cull backfaces
10489         //TriangleNormal(v[0], v[1], v[2], normal);
10490         //if (DotProduct(normal, localnormal) < 0.0f)
10491         //      continue;
10492         // clip by each of the box planes formed from the projection matrix
10493         // if anything survives, we emit the decal
10494         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]);
10495         if (numpoints < 3)
10496                 return;
10497         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]);
10498         if (numpoints < 3)
10499                 return;
10500         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]);
10501         if (numpoints < 3)
10502                 return;
10503         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]);
10504         if (numpoints < 3)
10505                 return;
10506         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]);
10507         if (numpoints < 3)
10508                 return;
10509         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]);
10510         if (numpoints < 3)
10511                 return;
10512         // some part of the triangle survived, so we have to accept it...
10513         if (dynamic)
10514         {
10515                 // dynamic always uses the original triangle
10516                 numpoints = 3;
10517                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10518                 {
10519                         index = 3*e[cornerindex];
10520                         VectorCopy(vertex3f + index, v[cornerindex]);
10521                 }
10522         }
10523         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10524         {
10525                 // convert vertex positions to texcoords
10526                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10527                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10528                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10529                 // calculate distance fade from the projection origin
10530                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10531                 f = bound(0.0f, f, 1.0f);
10532                 c[cornerindex][0] = r * f;
10533                 c[cornerindex][1] = g * f;
10534                 c[cornerindex][2] = b * f;
10535                 c[cornerindex][3] = 1.0f;
10536                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10537         }
10538         if (dynamic)
10539                 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);
10540         else
10541                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10542                         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);
10543 }
10544 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)
10545 {
10546         matrix4x4_t projection;
10547         decalsystem_t *decalsystem;
10548         qboolean dynamic;
10549         dp_model_t *model;
10550         const msurface_t *surface;
10551         const msurface_t *surfaces;
10552         const int *surfacelist;
10553         const texture_t *texture;
10554         int numtriangles;
10555         int numsurfacelist;
10556         int surfacelistindex;
10557         int surfaceindex;
10558         int triangleindex;
10559         float localorigin[3];
10560         float localnormal[3];
10561         float localmins[3];
10562         float localmaxs[3];
10563         float localsize;
10564         //float normal[3];
10565         float planes[6][4];
10566         float angles[3];
10567         bih_t *bih;
10568         int bih_triangles_count;
10569         int bih_triangles[256];
10570         int bih_surfaces[256];
10571
10572         decalsystem = &ent->decalsystem;
10573         model = ent->model;
10574         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10575         {
10576                 R_DecalSystem_Reset(&ent->decalsystem);
10577                 return;
10578         }
10579
10580         if (!model->brush.data_leafs && !cl_decals_models.integer)
10581         {
10582                 if (decalsystem->model)
10583                         R_DecalSystem_Reset(decalsystem);
10584                 return;
10585         }
10586
10587         if (decalsystem->model != model)
10588                 R_DecalSystem_Reset(decalsystem);
10589         decalsystem->model = model;
10590
10591         RSurf_ActiveModelEntity(ent, true, false, false);
10592
10593         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10594         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10595         VectorNormalize(localnormal);
10596         localsize = worldsize*rsurface.inversematrixscale;
10597         localmins[0] = localorigin[0] - localsize;
10598         localmins[1] = localorigin[1] - localsize;
10599         localmins[2] = localorigin[2] - localsize;
10600         localmaxs[0] = localorigin[0] + localsize;
10601         localmaxs[1] = localorigin[1] + localsize;
10602         localmaxs[2] = localorigin[2] + localsize;
10603
10604         //VectorCopy(localnormal, planes[4]);
10605         //VectorVectors(planes[4], planes[2], planes[0]);
10606         AnglesFromVectors(angles, localnormal, NULL, false);
10607         AngleVectors(angles, planes[0], planes[2], planes[4]);
10608         VectorNegate(planes[0], planes[1]);
10609         VectorNegate(planes[2], planes[3]);
10610         VectorNegate(planes[4], planes[5]);
10611         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10612         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10613         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10614         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10615         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10616         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10617
10618 #if 1
10619 // works
10620 {
10621         matrix4x4_t forwardprojection;
10622         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10623         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10624 }
10625 #else
10626 // broken
10627 {
10628         float projectionvector[4][3];
10629         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10630         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10631         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10632         projectionvector[0][0] = planes[0][0] * ilocalsize;
10633         projectionvector[0][1] = planes[1][0] * ilocalsize;
10634         projectionvector[0][2] = planes[2][0] * ilocalsize;
10635         projectionvector[1][0] = planes[0][1] * ilocalsize;
10636         projectionvector[1][1] = planes[1][1] * ilocalsize;
10637         projectionvector[1][2] = planes[2][1] * ilocalsize;
10638         projectionvector[2][0] = planes[0][2] * ilocalsize;
10639         projectionvector[2][1] = planes[1][2] * ilocalsize;
10640         projectionvector[2][2] = planes[2][2] * ilocalsize;
10641         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10642         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10643         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10644         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10645 }
10646 #endif
10647
10648         dynamic = model->surfmesh.isanimated;
10649         numsurfacelist = model->nummodelsurfaces;
10650         surfacelist = model->sortedmodelsurfaces;
10651         surfaces = model->data_surfaces;
10652
10653         bih = NULL;
10654         bih_triangles_count = -1;
10655         if(!dynamic)
10656         {
10657                 if(model->render_bih.numleafs)
10658                         bih = &model->render_bih;
10659                 else if(model->collision_bih.numleafs)
10660                         bih = &model->collision_bih;
10661         }
10662         if(bih)
10663                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10664         if(bih_triangles_count == 0)
10665                 return;
10666         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10667                 return;
10668         if(bih_triangles_count > 0)
10669         {
10670                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10671                 {
10672                         surfaceindex = bih_surfaces[triangleindex];
10673                         surface = surfaces + surfaceindex;
10674                         texture = surface->texture;
10675                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10676                                 continue;
10677                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10678                                 continue;
10679                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10680                 }
10681         }
10682         else
10683         {
10684                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10685                 {
10686                         surfaceindex = surfacelist[surfacelistindex];
10687                         surface = surfaces + surfaceindex;
10688                         // check cull box first because it rejects more than any other check
10689                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10690                                 continue;
10691                         // skip transparent surfaces
10692                         texture = surface->texture;
10693                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10694                                 continue;
10695                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10696                                 continue;
10697                         numtriangles = surface->num_triangles;
10698                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10699                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10700                 }
10701         }
10702 }
10703
10704 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10705 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)
10706 {
10707         int renderentityindex;
10708         float worldmins[3];
10709         float worldmaxs[3];
10710         entity_render_t *ent;
10711
10712         if (!cl_decals_newsystem.integer)
10713                 return;
10714
10715         worldmins[0] = worldorigin[0] - worldsize;
10716         worldmins[1] = worldorigin[1] - worldsize;
10717         worldmins[2] = worldorigin[2] - worldsize;
10718         worldmaxs[0] = worldorigin[0] + worldsize;
10719         worldmaxs[1] = worldorigin[1] + worldsize;
10720         worldmaxs[2] = worldorigin[2] + worldsize;
10721
10722         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10723
10724         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10725         {
10726                 ent = r_refdef.scene.entities[renderentityindex];
10727                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10728                         continue;
10729
10730                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10731         }
10732 }
10733
10734 typedef struct r_decalsystem_splatqueue_s
10735 {
10736         vec3_t worldorigin;
10737         vec3_t worldnormal;
10738         float color[4];
10739         float tcrange[4];
10740         float worldsize;
10741         int decalsequence;
10742 }
10743 r_decalsystem_splatqueue_t;
10744
10745 int r_decalsystem_numqueued = 0;
10746 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10747
10748 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)
10749 {
10750         r_decalsystem_splatqueue_t *queue;
10751
10752         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10753                 return;
10754
10755         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10756         VectorCopy(worldorigin, queue->worldorigin);
10757         VectorCopy(worldnormal, queue->worldnormal);
10758         Vector4Set(queue->color, r, g, b, a);
10759         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10760         queue->worldsize = worldsize;
10761         queue->decalsequence = cl.decalsequence++;
10762 }
10763
10764 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10765 {
10766         int i;
10767         r_decalsystem_splatqueue_t *queue;
10768
10769         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10770                 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);
10771         r_decalsystem_numqueued = 0;
10772 }
10773
10774 extern cvar_t cl_decals_max;
10775 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10776 {
10777         int i;
10778         decalsystem_t *decalsystem = &ent->decalsystem;
10779         int numdecals;
10780         int killsequence;
10781         tridecal_t *decal;
10782         float frametime;
10783         float lifetime;
10784
10785         if (!decalsystem->numdecals)
10786                 return;
10787
10788         if (r_showsurfaces.integer)
10789                 return;
10790
10791         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10792         {
10793                 R_DecalSystem_Reset(decalsystem);
10794                 return;
10795         }
10796
10797         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10798         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10799
10800         if (decalsystem->lastupdatetime)
10801                 frametime = (cl.time - decalsystem->lastupdatetime);
10802         else
10803                 frametime = 0;
10804         decalsystem->lastupdatetime = cl.time;
10805         decal = decalsystem->decals;
10806         numdecals = decalsystem->numdecals;
10807
10808         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10809         {
10810                 if (decal->color4f[0][3])
10811                 {
10812                         decal->lived += frametime;
10813                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10814                         {
10815                                 memset(decal, 0, sizeof(*decal));
10816                                 if (decalsystem->freedecal > i)
10817                                         decalsystem->freedecal = i;
10818                         }
10819                 }
10820         }
10821         decal = decalsystem->decals;
10822         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10823                 numdecals--;
10824
10825         // collapse the array by shuffling the tail decals into the gaps
10826         for (;;)
10827         {
10828                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10829                         decalsystem->freedecal++;
10830                 if (decalsystem->freedecal == numdecals)
10831                         break;
10832                 decal[decalsystem->freedecal] = decal[--numdecals];
10833         }
10834
10835         decalsystem->numdecals = numdecals;
10836
10837         if (numdecals <= 0)
10838         {
10839                 // if there are no decals left, reset decalsystem
10840                 R_DecalSystem_Reset(decalsystem);
10841         }
10842 }
10843
10844 extern skinframe_t *decalskinframe;
10845 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10846 {
10847         int i;
10848         decalsystem_t *decalsystem = &ent->decalsystem;
10849         int numdecals;
10850         tridecal_t *decal;
10851         float faderate;
10852         float alpha;
10853         float *v3f;
10854         float *c4f;
10855         float *t2f;
10856         const int *e;
10857         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10858         int numtris = 0;
10859
10860         numdecals = decalsystem->numdecals;
10861         if (!numdecals)
10862                 return;
10863
10864         if (r_showsurfaces.integer)
10865                 return;
10866
10867         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10868         {
10869                 R_DecalSystem_Reset(decalsystem);
10870                 return;
10871         }
10872
10873         // if the model is static it doesn't matter what value we give for
10874         // wantnormals and wanttangents, so this logic uses only rules applicable
10875         // to a model, knowing that they are meaningless otherwise
10876         if (ent == r_refdef.scene.worldentity)
10877                 RSurf_ActiveWorldEntity();
10878         else
10879                 RSurf_ActiveModelEntity(ent, false, false, false);
10880
10881         decalsystem->lastupdatetime = cl.time;
10882         decal = decalsystem->decals;
10883
10884         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10885
10886         // update vertex positions for animated models
10887         v3f = decalsystem->vertex3f;
10888         c4f = decalsystem->color4f;
10889         t2f = decalsystem->texcoord2f;
10890         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10891         {
10892                 if (!decal->color4f[0][3])
10893                         continue;
10894
10895                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10896                         continue;
10897
10898                 // skip backfaces
10899                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10900                         continue;
10901
10902                 // update color values for fading decals
10903                 if (decal->lived >= cl_decals_time.value)
10904                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10905                 else
10906                         alpha = 1.0f;
10907
10908                 c4f[ 0] = decal->color4f[0][0] * alpha;
10909                 c4f[ 1] = decal->color4f[0][1] * alpha;
10910                 c4f[ 2] = decal->color4f[0][2] * alpha;
10911                 c4f[ 3] = 1;
10912                 c4f[ 4] = decal->color4f[1][0] * alpha;
10913                 c4f[ 5] = decal->color4f[1][1] * alpha;
10914                 c4f[ 6] = decal->color4f[1][2] * alpha;
10915                 c4f[ 7] = 1;
10916                 c4f[ 8] = decal->color4f[2][0] * alpha;
10917                 c4f[ 9] = decal->color4f[2][1] * alpha;
10918                 c4f[10] = decal->color4f[2][2] * alpha;
10919                 c4f[11] = 1;
10920
10921                 t2f[0] = decal->texcoord2f[0][0];
10922                 t2f[1] = decal->texcoord2f[0][1];
10923                 t2f[2] = decal->texcoord2f[1][0];
10924                 t2f[3] = decal->texcoord2f[1][1];
10925                 t2f[4] = decal->texcoord2f[2][0];
10926                 t2f[5] = decal->texcoord2f[2][1];
10927
10928                 // update vertex positions for animated models
10929                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10930                 {
10931                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10932                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10933                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10934                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10935                 }
10936                 else
10937                 {
10938                         VectorCopy(decal->vertex3f[0], v3f);
10939                         VectorCopy(decal->vertex3f[1], v3f + 3);
10940                         VectorCopy(decal->vertex3f[2], v3f + 6);
10941                 }
10942
10943                 if (r_refdef.fogenabled)
10944                 {
10945                         alpha = RSurf_FogVertex(v3f);
10946                         VectorScale(c4f, alpha, c4f);
10947                         alpha = RSurf_FogVertex(v3f + 3);
10948                         VectorScale(c4f + 4, alpha, c4f + 4);
10949                         alpha = RSurf_FogVertex(v3f + 6);
10950                         VectorScale(c4f + 8, alpha, c4f + 8);
10951                 }
10952
10953                 v3f += 9;
10954                 c4f += 12;
10955                 t2f += 6;
10956                 numtris++;
10957         }
10958
10959         if (numtris > 0)
10960         {
10961                 r_refdef.stats.drawndecals += numtris;
10962
10963                 // now render the decals all at once
10964                 // (this assumes they all use one particle font texture!)
10965                 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);
10966 //              R_Mesh_ResetTextureState();
10967                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10968                 GL_DepthMask(false);
10969                 GL_DepthRange(0, 1);
10970                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10971                 GL_DepthTest(true);
10972                 GL_CullFace(GL_NONE);
10973                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10974                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10975                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10976         }
10977 }
10978
10979 static void R_DrawModelDecals(void)
10980 {
10981         int i, numdecals;
10982
10983         // fade faster when there are too many decals
10984         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10985         for (i = 0;i < r_refdef.scene.numentities;i++)
10986                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10987
10988         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10989         for (i = 0;i < r_refdef.scene.numentities;i++)
10990                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10991                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10992
10993         R_DecalSystem_ApplySplatEntitiesQueue();
10994
10995         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10996         for (i = 0;i < r_refdef.scene.numentities;i++)
10997                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10998
10999         r_refdef.stats.totaldecals += numdecals;
11000
11001         if (r_showsurfaces.integer)
11002                 return;
11003
11004         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11005
11006         for (i = 0;i < r_refdef.scene.numentities;i++)
11007         {
11008                 if (!r_refdef.viewcache.entityvisible[i])
11009                         continue;
11010                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11011                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11012         }
11013 }
11014
11015 extern cvar_t mod_collision_bih;
11016 void R_DrawDebugModel(void)
11017 {
11018         entity_render_t *ent = rsurface.entity;
11019         int i, j, k, l, flagsmask;
11020         const msurface_t *surface;
11021         dp_model_t *model = ent->model;
11022         vec3_t v;
11023
11024         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11025                 return;
11026
11027         if (r_showoverdraw.value > 0)
11028         {
11029                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11030                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11031                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11032                 GL_DepthTest(false);
11033                 GL_DepthMask(false);
11034                 GL_DepthRange(0, 1);
11035                 GL_BlendFunc(GL_ONE, GL_ONE);
11036                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11037                 {
11038                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11039                                 continue;
11040                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11041                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11042                         {
11043                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11044                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11045                                 if (!rsurface.texture->currentlayers->depthmask)
11046                                         GL_Color(c, 0, 0, 1.0f);
11047                                 else if (ent == r_refdef.scene.worldentity)
11048                                         GL_Color(c, c, c, 1.0f);
11049                                 else
11050                                         GL_Color(0, c, 0, 1.0f);
11051                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11052                                 RSurf_DrawBatch();
11053                         }
11054                 }
11055                 rsurface.texture = NULL;
11056         }
11057
11058         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11059
11060 //      R_Mesh_ResetTextureState();
11061         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11062         GL_DepthRange(0, 1);
11063         GL_DepthTest(!r_showdisabledepthtest.integer);
11064         GL_DepthMask(false);
11065         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11066
11067         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11068         {
11069                 int triangleindex;
11070                 int bihleafindex;
11071                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11072                 const q3mbrush_t *brush;
11073                 const bih_t *bih = &model->collision_bih;
11074                 const bih_leaf_t *bihleaf;
11075                 float vertex3f[3][3];
11076                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11077                 cullbox = false;
11078                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11079                 {
11080                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11081                                 continue;
11082                         switch (bihleaf->type)
11083                         {
11084                         case BIH_BRUSH:
11085                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11086                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11087                                 {
11088                                         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);
11089                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11090                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11091                                 }
11092                                 break;
11093                         case BIH_COLLISIONTRIANGLE:
11094                                 triangleindex = bihleaf->itemindex;
11095                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11096                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11097                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11098                                 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);
11099                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11100                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11101                                 break;
11102                         case BIH_RENDERTRIANGLE:
11103                                 triangleindex = bihleaf->itemindex;
11104                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11105                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11106                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11107                                 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);
11108                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11109                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11110                                 break;
11111                         }
11112                 }
11113         }
11114
11115         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11116
11117         if (r_showtris.integer && qglPolygonMode)
11118         {
11119                 if (r_showdisabledepthtest.integer)
11120                 {
11121                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11122                         GL_DepthMask(false);
11123                 }
11124                 else
11125                 {
11126                         GL_BlendFunc(GL_ONE, GL_ZERO);
11127                         GL_DepthMask(true);
11128                 }
11129                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11130                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11131                 {
11132                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11133                                 continue;
11134                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11135                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11136                         {
11137                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11138                                 if (!rsurface.texture->currentlayers->depthmask)
11139                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11140                                 else if (ent == r_refdef.scene.worldentity)
11141                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11142                                 else
11143                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11144                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11145                                 RSurf_DrawBatch();
11146                         }
11147                 }
11148                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11149                 rsurface.texture = NULL;
11150         }
11151
11152         if (r_shownormals.value != 0 && qglBegin)
11153         {
11154                 if (r_showdisabledepthtest.integer)
11155                 {
11156                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11157                         GL_DepthMask(false);
11158                 }
11159                 else
11160                 {
11161                         GL_BlendFunc(GL_ONE, GL_ZERO);
11162                         GL_DepthMask(true);
11163                 }
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                                 qglBegin(GL_LINES);
11173                                 if (r_shownormals.value < 0)
11174                                 {
11175                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11176                                         {
11177                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11178                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11179                                                 qglVertex3f(v[0], v[1], v[2]);
11180                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11181                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11182                                                 qglVertex3f(v[0], v[1], v[2]);
11183                                         }
11184                                 }
11185                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11186                                 {
11187                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11188                                         {
11189                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11190                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11191                                                 qglVertex3f(v[0], v[1], v[2]);
11192                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11193                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11194                                                 qglVertex3f(v[0], v[1], v[2]);
11195                                         }
11196                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11197                                         {
11198                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11199                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11200                                                 qglVertex3f(v[0], v[1], v[2]);
11201                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11202                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11203                                                 qglVertex3f(v[0], v[1], v[2]);
11204                                         }
11205                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11206                                         {
11207                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11208                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11209                                                 qglVertex3f(v[0], v[1], v[2]);
11210                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11211                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11212                                                 qglVertex3f(v[0], v[1], v[2]);
11213                                         }
11214                                 }
11215                                 qglEnd();
11216                                 CHECKGLERROR
11217                         }
11218                 }
11219                 rsurface.texture = NULL;
11220         }
11221 }
11222
11223 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11224 int r_maxsurfacelist = 0;
11225 const msurface_t **r_surfacelist = NULL;
11226 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11227 {
11228         int i, j, endj, flagsmask;
11229         dp_model_t *model = r_refdef.scene.worldmodel;
11230         msurface_t *surfaces;
11231         unsigned char *update;
11232         int numsurfacelist = 0;
11233         if (model == NULL)
11234                 return;
11235
11236         if (r_maxsurfacelist < model->num_surfaces)
11237         {
11238                 r_maxsurfacelist = model->num_surfaces;
11239                 if (r_surfacelist)
11240                         Mem_Free((msurface_t**)r_surfacelist);
11241                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11242         }
11243
11244         RSurf_ActiveWorldEntity();
11245
11246         surfaces = model->data_surfaces;
11247         update = model->brushq1.lightmapupdateflags;
11248
11249         // update light styles on this submodel
11250         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11251         {
11252                 model_brush_lightstyleinfo_t *style;
11253                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11254                 {
11255                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11256                         {
11257                                 int *list = style->surfacelist;
11258                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11259                                 for (j = 0;j < style->numsurfaces;j++)
11260                                         update[list[j]] = true;
11261                         }
11262                 }
11263         }
11264
11265         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11266
11267         if (debug)
11268         {
11269                 R_DrawDebugModel();
11270                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11271                 return;
11272         }
11273
11274         rsurface.lightmaptexture = NULL;
11275         rsurface.deluxemaptexture = NULL;
11276         rsurface.uselightmaptexture = false;
11277         rsurface.texture = NULL;
11278         rsurface.rtlight = NULL;
11279         numsurfacelist = 0;
11280         // add visible surfaces to draw list
11281         for (i = 0;i < model->nummodelsurfaces;i++)
11282         {
11283                 j = model->sortedmodelsurfaces[i];
11284                 if (r_refdef.viewcache.world_surfacevisible[j])
11285                         r_surfacelist[numsurfacelist++] = surfaces + j;
11286         }
11287         // update lightmaps if needed
11288         if (model->brushq1.firstrender)
11289         {
11290                 model->brushq1.firstrender = false;
11291                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11292                         if (update[j])
11293                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11294         }
11295         else if (update)
11296         {
11297                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11298                         if (r_refdef.viewcache.world_surfacevisible[j])
11299                                 if (update[j])
11300                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11301         }
11302         // don't do anything if there were no surfaces
11303         if (!numsurfacelist)
11304         {
11305                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11306                 return;
11307         }
11308         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11309
11310         // add to stats if desired
11311         if (r_speeds.integer && !skysurfaces && !depthonly)
11312         {
11313                 r_refdef.stats.world_surfaces += numsurfacelist;
11314                 for (j = 0;j < numsurfacelist;j++)
11315                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11316         }
11317
11318         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11319 }
11320
11321 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11322 {
11323         int i, j, endj, flagsmask;
11324         dp_model_t *model = ent->model;
11325         msurface_t *surfaces;
11326         unsigned char *update;
11327         int numsurfacelist = 0;
11328         if (model == NULL)
11329                 return;
11330
11331         if (r_maxsurfacelist < model->num_surfaces)
11332         {
11333                 r_maxsurfacelist = model->num_surfaces;
11334                 if (r_surfacelist)
11335                         Mem_Free((msurface_t **)r_surfacelist);
11336                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11337         }
11338
11339         // if the model is static it doesn't matter what value we give for
11340         // wantnormals and wanttangents, so this logic uses only rules applicable
11341         // to a model, knowing that they are meaningless otherwise
11342         if (ent == r_refdef.scene.worldentity)
11343                 RSurf_ActiveWorldEntity();
11344         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11345                 RSurf_ActiveModelEntity(ent, false, false, false);
11346         else if (prepass)
11347                 RSurf_ActiveModelEntity(ent, true, true, true);
11348         else if (depthonly)
11349         {
11350                 switch (vid.renderpath)
11351                 {
11352                 case RENDERPATH_GL20:
11353                 case RENDERPATH_D3D9:
11354                 case RENDERPATH_D3D10:
11355                 case RENDERPATH_D3D11:
11356                 case RENDERPATH_SOFT:
11357                 case RENDERPATH_GLES2:
11358                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11359                         break;
11360                 case RENDERPATH_GL11:
11361                 case RENDERPATH_GL13:
11362                 case RENDERPATH_GLES1:
11363                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11364                         break;
11365                 }
11366         }
11367         else
11368         {
11369                 switch (vid.renderpath)
11370                 {
11371                 case RENDERPATH_GL20:
11372                 case RENDERPATH_D3D9:
11373                 case RENDERPATH_D3D10:
11374                 case RENDERPATH_D3D11:
11375                 case RENDERPATH_SOFT:
11376                 case RENDERPATH_GLES2:
11377                         RSurf_ActiveModelEntity(ent, true, true, false);
11378                         break;
11379                 case RENDERPATH_GL11:
11380                 case RENDERPATH_GL13:
11381                 case RENDERPATH_GLES1:
11382                         RSurf_ActiveModelEntity(ent, true, false, false);
11383                         break;
11384                 }
11385         }
11386
11387         surfaces = model->data_surfaces;
11388         update = model->brushq1.lightmapupdateflags;
11389
11390         // update light styles
11391         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11392         {
11393                 model_brush_lightstyleinfo_t *style;
11394                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11395                 {
11396                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11397                         {
11398                                 int *list = style->surfacelist;
11399                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11400                                 for (j = 0;j < style->numsurfaces;j++)
11401                                         update[list[j]] = true;
11402                         }
11403                 }
11404         }
11405
11406         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11407
11408         if (debug)
11409         {
11410                 R_DrawDebugModel();
11411                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11412                 return;
11413         }
11414
11415         rsurface.lightmaptexture = NULL;
11416         rsurface.deluxemaptexture = NULL;
11417         rsurface.uselightmaptexture = false;
11418         rsurface.texture = NULL;
11419         rsurface.rtlight = NULL;
11420         numsurfacelist = 0;
11421         // add visible surfaces to draw list
11422         for (i = 0;i < model->nummodelsurfaces;i++)
11423                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11424         // don't do anything if there were no surfaces
11425         if (!numsurfacelist)
11426         {
11427                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11428                 return;
11429         }
11430         // update lightmaps if needed
11431         if (update)
11432         {
11433                 int updated = 0;
11434                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11435                 {
11436                         if (update[j])
11437                         {
11438                                 updated++;
11439                                 R_BuildLightMap(ent, surfaces + j);
11440                         }
11441                 }
11442         }
11443         if (update)
11444                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11445                         if (update[j])
11446                                 R_BuildLightMap(ent, surfaces + j);
11447         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11448
11449         // add to stats if desired
11450         if (r_speeds.integer && !skysurfaces && !depthonly)
11451         {
11452                 r_refdef.stats.entities_surfaces += numsurfacelist;
11453                 for (j = 0;j < numsurfacelist;j++)
11454                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11455         }
11456
11457         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11458 }
11459
11460 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11461 {
11462         static texture_t texture;
11463         static msurface_t surface;
11464         const msurface_t *surfacelist = &surface;
11465
11466         // fake enough texture and surface state to render this geometry
11467
11468         texture.update_lastrenderframe = -1; // regenerate this texture
11469         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11470         texture.currentskinframe = skinframe;
11471         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11472         texture.offsetmapping = OFFSETMAPPING_OFF;
11473         texture.offsetscale = 1;
11474         texture.specularscalemod = 1;
11475         texture.specularpowermod = 1;
11476
11477         surface.texture = &texture;
11478         surface.num_triangles = numtriangles;
11479         surface.num_firsttriangle = firsttriangle;
11480         surface.num_vertices = numvertices;
11481         surface.num_firstvertex = firstvertex;
11482
11483         // now render it
11484         rsurface.texture = R_GetCurrentTexture(surface.texture);
11485         rsurface.lightmaptexture = NULL;
11486         rsurface.deluxemaptexture = NULL;
11487         rsurface.uselightmaptexture = false;
11488         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11489 }
11490
11491 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)
11492 {
11493         static msurface_t surface;
11494         const msurface_t *surfacelist = &surface;
11495
11496         // fake enough texture and surface state to render this geometry
11497         surface.texture = texture;
11498         surface.num_triangles = numtriangles;
11499         surface.num_firsttriangle = firsttriangle;
11500         surface.num_vertices = numvertices;
11501         surface.num_firstvertex = firstvertex;
11502
11503         // now render it
11504         rsurface.texture = R_GetCurrentTexture(surface.texture);
11505         rsurface.lightmaptexture = NULL;
11506         rsurface.deluxemaptexture = NULL;
11507         rsurface.uselightmaptexture = false;
11508         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11509 }