]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Move some sprite-related cvars to model_sprite.c.
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 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)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 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"};
203
204 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"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
212
213 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."};
214
215 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)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 };
674
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
677 {
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 };
695
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
697 {
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenDepth;
753         int tex_Texture_ScreenNormalMap;
754         int tex_Texture_ScreenDiffuse;
755         int tex_Texture_ScreenSpecular;
756         int tex_Texture_ReflectMask;
757         int tex_Texture_ReflectCube;
758         int tex_Texture_BounceGrid;
759         /// locations of detected uniforms in program object, or -1 if not found
760         int loc_Texture_First;
761         int loc_Texture_Second;
762         int loc_Texture_GammaRamps;
763         int loc_Texture_Normal;
764         int loc_Texture_Color;
765         int loc_Texture_Gloss;
766         int loc_Texture_Glow;
767         int loc_Texture_SecondaryNormal;
768         int loc_Texture_SecondaryColor;
769         int loc_Texture_SecondaryGloss;
770         int loc_Texture_SecondaryGlow;
771         int loc_Texture_Pants;
772         int loc_Texture_Shirt;
773         int loc_Texture_FogHeightTexture;
774         int loc_Texture_FogMask;
775         int loc_Texture_Lightmap;
776         int loc_Texture_Deluxemap;
777         int loc_Texture_Attenuation;
778         int loc_Texture_Cube;
779         int loc_Texture_Refraction;
780         int loc_Texture_Reflection;
781         int loc_Texture_ShadowMap2D;
782         int loc_Texture_CubeProjection;
783         int loc_Texture_ScreenDepth;
784         int loc_Texture_ScreenNormalMap;
785         int loc_Texture_ScreenDiffuse;
786         int loc_Texture_ScreenSpecular;
787         int loc_Texture_ReflectMask;
788         int loc_Texture_ReflectCube;
789         int loc_Texture_BounceGrid;
790         int loc_Alpha;
791         int loc_BloomBlur_Parameters;
792         int loc_ClientTime;
793         int loc_Color_Ambient;
794         int loc_Color_Diffuse;
795         int loc_Color_Specular;
796         int loc_Color_Glow;
797         int loc_Color_Pants;
798         int loc_Color_Shirt;
799         int loc_DeferredColor_Ambient;
800         int loc_DeferredColor_Diffuse;
801         int loc_DeferredColor_Specular;
802         int loc_DeferredMod_Diffuse;
803         int loc_DeferredMod_Specular;
804         int loc_DistortScaleRefractReflect;
805         int loc_EyePosition;
806         int loc_FogColor;
807         int loc_FogHeightFade;
808         int loc_FogPlane;
809         int loc_FogPlaneViewDist;
810         int loc_FogRangeRecip;
811         int loc_LightColor;
812         int loc_LightDir;
813         int loc_LightPosition;
814         int loc_OffsetMapping_ScaleSteps;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845 }
846 r_glsl_permutation_t;
847
848 #define SHADERPERMUTATION_HASHSIZE 256
849
850
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
853 enum
854 {
855         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
861         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
862 };
863 #define SHADERSTATICPARMS_COUNT 7
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
871 {
872         static int r_compileshader_staticparms_save[1];
873         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
875
876         // detect all
877         if (r_glsl_saturation_redcompensate.integer)
878                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879         if (r_glsl_vertextextureblend_usebothalphas.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881         if (r_shadow_glossexact.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883         if (r_glsl_postprocess.integer)
884         {
885                 if (r_glsl_postprocess_uservec1_enable.integer)
886                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887                 if (r_glsl_postprocess_uservec2_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889                 if (r_glsl_postprocess_uservec3_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891                 if (r_glsl_postprocess_uservec4_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
893         }
894         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
895 }
896
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
900         else \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
903 {
904         shaderstaticparms_count = 0;
905
906         // emit all
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
914 }
915
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
922
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
924 {
925         //unsigned int hashdepth = 0;
926         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927         r_glsl_permutation_t *p;
928         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
929         {
930                 if (p->mode == mode && p->permutation == permutation)
931                 {
932                         //if (hashdepth > 10)
933                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
934                         return p;
935                 }
936                 //hashdepth++;
937         }
938         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
939         p->mode = mode;
940         p->permutation = permutation;
941         p->hashnext = r_glsl_permutationhash[mode][hashindex];
942         r_glsl_permutationhash[mode][hashindex] = p;
943         //if (hashdepth > 10)
944         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945         return p;
946 }
947
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
949 {
950         char *shaderstring;
951         if (!filename || !filename[0])
952                 return NULL;
953         if (!strcmp(filename, "glsl/default.glsl"))
954         {
955                 if (!glslshaderstring)
956                 {
957                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958                         if (glslshaderstring)
959                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
960                         else
961                                 glslshaderstring = (char *)builtinshaderstring;
962                 }
963                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
965                 return shaderstring;
966         }
967         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968         if (shaderstring)
969         {
970                 if (printfromdisknotice)
971                         Con_DPrintf("from disk %s... ", filename);
972                 return shaderstring;
973         }
974         return shaderstring;
975 }
976
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
978 {
979         int i;
980         int sampler;
981         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982         char *vertexstring, *geometrystring, *fragmentstring;
983         char permutationname[256];
984         int vertstrings_count = 0;
985         int geomstrings_count = 0;
986         int fragstrings_count = 0;
987         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990
991         if (p->compiled)
992                 return;
993         p->compiled = true;
994         p->program = 0;
995
996         permutationname[0] = 0;
997         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
998         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1000
1001         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1002
1003         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004         if(vid.support.gl20shaders130)
1005         {
1006                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1012         }
1013
1014         // the first pretext is which type of shader to compile as
1015         // (later these will all be bound together as a program object)
1016         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1019
1020         // the second pretext is the mode (for example a light source)
1021         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1025
1026         // now add all the permutation pretexts
1027         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1028         {
1029                 if (permutation & (1<<i))
1030                 {
1031                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1035                 }
1036                 else
1037                 {
1038                         // keep line numbers correct
1039                         vertstrings_list[vertstrings_count++] = "\n";
1040                         geomstrings_list[geomstrings_count++] = "\n";
1041                         fragstrings_list[fragstrings_count++] = "\n";
1042                 }
1043         }
1044
1045         // add static parms
1046         R_CompileShader_AddStaticParms(mode, permutation);
1047         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048         vertstrings_count += shaderstaticparms_count;
1049         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         geomstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         fragstrings_count += shaderstaticparms_count;
1053
1054         // now append the shader text itself
1055         vertstrings_list[vertstrings_count++] = vertexstring;
1056         geomstrings_list[geomstrings_count++] = geometrystring;
1057         fragstrings_list[fragstrings_count++] = fragmentstring;
1058
1059         // if any sources were NULL, clear the respective list
1060         if (!vertexstring)
1061                 vertstrings_count = 0;
1062         if (!geometrystring)
1063                 geomstrings_count = 0;
1064         if (!fragmentstring)
1065                 fragstrings_count = 0;
1066
1067         // compile the shader program
1068         if (vertstrings_count + geomstrings_count + fragstrings_count)
1069                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1070         if (p->program)
1071         {
1072                 CHECKGLERROR
1073                 qglUseProgram(p->program);CHECKGLERROR
1074                 // look up all the uniform variable names we care about, so we don't
1075                 // have to look them up every time we set them
1076
1077                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1078                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1079                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1081                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1082                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1083                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1084                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1089                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1090                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1092                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1096                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1097                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1098                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1108                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1110                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1111                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1112                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1113                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1114                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1115                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1116                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1123                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1124                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1125                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1126                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1128                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1129                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1130                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1131                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1133                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1134                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1135                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1136                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1137                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1138                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1141                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1144                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1145                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1146                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1147                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1148                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1149                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1150                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1151                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1152                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162                 // initialize the samplers to refer to the texture units we use
1163                 p->tex_Texture_First = -1;
1164                 p->tex_Texture_Second = -1;
1165                 p->tex_Texture_GammaRamps = -1;
1166                 p->tex_Texture_Normal = -1;
1167                 p->tex_Texture_Color = -1;
1168                 p->tex_Texture_Gloss = -1;
1169                 p->tex_Texture_Glow = -1;
1170                 p->tex_Texture_SecondaryNormal = -1;
1171                 p->tex_Texture_SecondaryColor = -1;
1172                 p->tex_Texture_SecondaryGloss = -1;
1173                 p->tex_Texture_SecondaryGlow = -1;
1174                 p->tex_Texture_Pants = -1;
1175                 p->tex_Texture_Shirt = -1;
1176                 p->tex_Texture_FogHeightTexture = -1;
1177                 p->tex_Texture_FogMask = -1;
1178                 p->tex_Texture_Lightmap = -1;
1179                 p->tex_Texture_Deluxemap = -1;
1180                 p->tex_Texture_Attenuation = -1;
1181                 p->tex_Texture_Cube = -1;
1182                 p->tex_Texture_Refraction = -1;
1183                 p->tex_Texture_Reflection = -1;
1184                 p->tex_Texture_ShadowMap2D = -1;
1185                 p->tex_Texture_CubeProjection = -1;
1186                 p->tex_Texture_ScreenDepth = -1;
1187                 p->tex_Texture_ScreenNormalMap = -1;
1188                 p->tex_Texture_ScreenDiffuse = -1;
1189                 p->tex_Texture_ScreenSpecular = -1;
1190                 p->tex_Texture_ReflectMask = -1;
1191                 p->tex_Texture_ReflectCube = -1;
1192                 p->tex_Texture_BounceGrid = -1;
1193                 sampler = 0;
1194                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1195                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1196                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1197                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1198                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1199                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1200                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1201                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1205                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1206                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1207                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1209                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1210                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1211                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1212                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1213                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1214                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1215                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1216                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1217                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1221                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1223                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1224                 CHECKGLERROR
1225                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1226         }
1227         else
1228                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1229
1230         // free the strings
1231         if (vertexstring)
1232                 Mem_Free(vertexstring);
1233         if (geometrystring)
1234                 Mem_Free(geometrystring);
1235         if (fragmentstring)
1236                 Mem_Free(fragmentstring);
1237 }
1238
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1240 {
1241         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242         if (r_glsl_permutation != perm)
1243         {
1244                 r_glsl_permutation = perm;
1245                 if (!r_glsl_permutation->program)
1246                 {
1247                         if (!r_glsl_permutation->compiled)
1248                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1249                         if (!r_glsl_permutation->program)
1250                         {
1251                                 // remove features until we find a valid permutation
1252                                 int i;
1253                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1254                                 {
1255                                         // reduce i more quickly whenever it would not remove any bits
1256                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257                                         if (!(permutation & j))
1258                                                 continue;
1259                                         permutation -= j;
1260                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261                                         if (!r_glsl_permutation->compiled)
1262                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                                         if (r_glsl_permutation->program)
1264                                                 break;
1265                                 }
1266                                 if (i >= SHADERPERMUTATION_COUNT)
1267                                 {
1268                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         qglUseProgram(0);CHECKGLERROR
1271                                         return; // no bit left to clear, entire mode is broken
1272                                 }
1273                         }
1274                 }
1275                 CHECKGLERROR
1276                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1277         }
1278         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1281 }
1282
1283 #ifdef SUPPORTD3D
1284
1285 #ifdef SUPPORTD3D
1286 #include <d3d9.h>
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1289 #endif
1290
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1293 {
1294         /// hash lookup data
1295         struct r_hlsl_permutation_s *hashnext;
1296         unsigned int mode;
1297         unsigned int permutation;
1298
1299         /// indicates if we have tried compiling this permutation already
1300         qboolean compiled;
1301         /// NULL if compilation failed
1302         IDirect3DVertexShader9 *vertexshader;
1303         IDirect3DPixelShader9 *pixelshader;
1304 }
1305 r_hlsl_permutation_t;
1306
1307 typedef enum D3DVSREGISTER_e
1308 {
1309         D3DVSREGISTER_TexMatrix = 0, // float4x4
1310         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314         D3DVSREGISTER_ModelToLight = 20, // float4x4
1315         D3DVSREGISTER_EyePosition = 24,
1316         D3DVSREGISTER_FogPlane = 25,
1317         D3DVSREGISTER_LightDir = 26,
1318         D3DVSREGISTER_LightPosition = 27,
1319 }
1320 D3DVSREGISTER_t;
1321
1322 typedef enum D3DPSREGISTER_e
1323 {
1324         D3DPSREGISTER_Alpha = 0,
1325         D3DPSREGISTER_BloomBlur_Parameters = 1,
1326         D3DPSREGISTER_ClientTime = 2,
1327         D3DPSREGISTER_Color_Ambient = 3,
1328         D3DPSREGISTER_Color_Diffuse = 4,
1329         D3DPSREGISTER_Color_Specular = 5,
1330         D3DPSREGISTER_Color_Glow = 6,
1331         D3DPSREGISTER_Color_Pants = 7,
1332         D3DPSREGISTER_Color_Shirt = 8,
1333         D3DPSREGISTER_DeferredColor_Ambient = 9,
1334         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335         D3DPSREGISTER_DeferredColor_Specular = 11,
1336         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337         D3DPSREGISTER_DeferredMod_Specular = 13,
1338         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339         D3DPSREGISTER_EyePosition = 15, // unused
1340         D3DPSREGISTER_FogColor = 16,
1341         D3DPSREGISTER_FogHeightFade = 17,
1342         D3DPSREGISTER_FogPlane = 18,
1343         D3DPSREGISTER_FogPlaneViewDist = 19,
1344         D3DPSREGISTER_FogRangeRecip = 20,
1345         D3DPSREGISTER_LightColor = 21,
1346         D3DPSREGISTER_LightDir = 22, // unused
1347         D3DPSREGISTER_LightPosition = 23,
1348         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349         D3DPSREGISTER_PixelSize = 25,
1350         D3DPSREGISTER_ReflectColor = 26,
1351         D3DPSREGISTER_ReflectFactor = 27,
1352         D3DPSREGISTER_ReflectOffset = 28,
1353         D3DPSREGISTER_RefractColor = 29,
1354         D3DPSREGISTER_Saturation = 30,
1355         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357         D3DPSREGISTER_ScreenToDepth = 33,
1358         D3DPSREGISTER_ShadowMap_Parameters = 34,
1359         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360         D3DPSREGISTER_SpecularPower = 36,
1361         D3DPSREGISTER_UserVec1 = 37,
1362         D3DPSREGISTER_UserVec2 = 38,
1363         D3DPSREGISTER_UserVec3 = 39,
1364         D3DPSREGISTER_UserVec4 = 40,
1365         D3DPSREGISTER_ViewTintColor = 41,
1366         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367         D3DPSREGISTER_BloomColorSubtract = 43,
1368         D3DPSREGISTER_ViewToLight = 44, // float4x4
1369         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370         D3DPSREGISTER_NormalmapScrollBlend = 52,
1371         // next at 53
1372 }
1373 D3DPSREGISTER_t;
1374
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1381
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1383 {
1384         //unsigned int hashdepth = 0;
1385         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386         r_hlsl_permutation_t *p;
1387         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1388         {
1389                 if (p->mode == mode && p->permutation == permutation)
1390                 {
1391                         //if (hashdepth > 10)
1392                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1393                         return p;
1394                 }
1395                 //hashdepth++;
1396         }
1397         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1398         p->mode = mode;
1399         p->permutation = permutation;
1400         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401         r_hlsl_permutationhash[mode][hashindex] = p;
1402         //if (hashdepth > 10)
1403         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404         return p;
1405 }
1406
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1408 {
1409         char *shaderstring;
1410         if (!filename || !filename[0])
1411                 return NULL;
1412         if (!strcmp(filename, "hlsl/default.hlsl"))
1413         {
1414                 if (!hlslshaderstring)
1415                 {
1416                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417                         if (hlslshaderstring)
1418                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1419                         else
1420                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1421                 }
1422                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424                 return shaderstring;
1425         }
1426         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427         if (shaderstring)
1428         {
1429                 if (printfromdisknotice)
1430                         Con_DPrintf("from disk %s... ", filename);
1431                 return shaderstring;
1432         }
1433         return shaderstring;
1434 }
1435
1436 #include <d3dx9.h>
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1439
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1441 {
1442         DWORD *vsbin = NULL;
1443         DWORD *psbin = NULL;
1444         fs_offset_t vsbinsize;
1445         fs_offset_t psbinsize;
1446 //      IDirect3DVertexShader9 *vs = NULL;
1447 //      IDirect3DPixelShader9 *ps = NULL;
1448         ID3DXBuffer *vslog = NULL;
1449         ID3DXBuffer *vsbuffer = NULL;
1450         ID3DXConstantTable *vsconstanttable = NULL;
1451         ID3DXBuffer *pslog = NULL;
1452         ID3DXBuffer *psbuffer = NULL;
1453         ID3DXConstantTable *psconstanttable = NULL;
1454         int vsresult = 0;
1455         int psresult = 0;
1456         char temp[MAX_INPUTLINE];
1457         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458         qboolean debugshader = gl_paranoid.integer != 0;
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (!debugshader)
1462         {
1463                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1465         }
1466         if ((!vsbin && vertstring) || (!psbin && fragstring))
1467         {
1468                 const char* dllnames_d3dx9 [] =
1469                 {
1470                         "d3dx9_43.dll",
1471                         "d3dx9_42.dll",
1472                         "d3dx9_41.dll",
1473                         "d3dx9_40.dll",
1474                         "d3dx9_39.dll",
1475                         "d3dx9_38.dll",
1476                         "d3dx9_37.dll",
1477                         "d3dx9_36.dll",
1478                         "d3dx9_35.dll",
1479                         "d3dx9_34.dll",
1480                         "d3dx9_33.dll",
1481                         "d3dx9_32.dll",
1482                         "d3dx9_31.dll",
1483                         "d3dx9_30.dll",
1484                         "d3dx9_29.dll",
1485                         "d3dx9_28.dll",
1486                         "d3dx9_27.dll",
1487                         "d3dx9_26.dll",
1488                         "d3dx9_25.dll",
1489                         "d3dx9_24.dll",
1490                         NULL
1491                 };
1492                 dllhandle_t d3dx9_dll = NULL;
1493                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 dllfunction_t d3dx9_dllfuncs[] =
1497                 {
1498                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1499                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1500                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1501                         {NULL, NULL}
1502                 };
1503                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1504                 {
1505                         DWORD shaderflags = 0;
1506                         if (debugshader)
1507                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510                         if (vertstring && vertstring[0])
1511                         {
1512                                 if (debugshader)
1513                                 {
1514 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 }
1519                                 else
1520                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521                                 if (vsbuffer)
1522                                 {
1523                                         vsbinsize = vsbuffer->GetBufferSize();
1524                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526                                         vsbuffer->Release();
1527                                 }
1528                                 if (vslog)
1529                                 {
1530                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1532                                         vslog->Release();
1533                                 }
1534                         }
1535                         if (fragstring && fragstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 }
1544                                 else
1545                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546                                 if (psbuffer)
1547                                 {
1548                                         psbinsize = psbuffer->GetBufferSize();
1549                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551                                         psbuffer->Release();
1552                                 }
1553                                 if (pslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         pslog->Release();
1558                                 }
1559                         }
1560                         Sys_UnloadLibrary(&d3dx9_dll);
1561                 }
1562                 else
1563                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1564         }
1565         if (vsbin && psbin)
1566         {
1567                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568                 if (FAILED(vsresult))
1569                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571                 if (FAILED(psresult))
1572                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1573         }
1574         // free the shader data
1575         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1577 }
1578
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1580 {
1581         int i;
1582         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583         int vertstring_length = 0;
1584         int geomstring_length = 0;
1585         int fragstring_length = 0;
1586         char *t;
1587         char *vertexstring, *geometrystring, *fragmentstring;
1588         char *vertstring, *geomstring, *fragstring;
1589         char permutationname[256];
1590         char cachename[256];
1591         int vertstrings_count = 0;
1592         int geomstrings_count = 0;
1593         int fragstrings_count = 0;
1594         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597
1598         if (p->compiled)
1599                 return;
1600         p->compiled = true;
1601         p->vertexshader = NULL;
1602         p->pixelshader = NULL;
1603
1604         permutationname[0] = 0;
1605         cachename[0] = 0;
1606         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1609
1610         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611         strlcat(cachename, "hlsl/", sizeof(cachename));
1612
1613         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614         vertstrings_count = 0;
1615         geomstrings_count = 0;
1616         fragstrings_count = 0;
1617         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1620
1621         // the first pretext is which type of shader to compile as
1622         // (later these will all be bound together as a program object)
1623         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1626
1627         // the second pretext is the mode (for example a light source)
1628         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632         strlcat(cachename, modeinfo->name, sizeof(cachename));
1633
1634         // now add all the permutation pretexts
1635         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1636         {
1637                 if (permutation & (1<<i))
1638                 {
1639                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1644                 }
1645                 else
1646                 {
1647                         // keep line numbers correct
1648                         vertstrings_list[vertstrings_count++] = "\n";
1649                         geomstrings_list[geomstrings_count++] = "\n";
1650                         fragstrings_list[fragstrings_count++] = "\n";
1651                 }
1652         }
1653
1654         // add static parms
1655         R_CompileShader_AddStaticParms(mode, permutation);
1656         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         vertstrings_count += shaderstaticparms_count;
1658         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         geomstrings_count += shaderstaticparms_count;
1660         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         fragstrings_count += shaderstaticparms_count;
1662
1663         // replace spaces in the cachename with _ characters
1664         for (i = 0;cachename[i];i++)
1665                 if (cachename[i] == ' ')
1666                         cachename[i] = '_';
1667
1668         // now append the shader text itself
1669         vertstrings_list[vertstrings_count++] = vertexstring;
1670         geomstrings_list[geomstrings_count++] = geometrystring;
1671         fragstrings_list[fragstrings_count++] = fragmentstring;
1672
1673         // if any sources were NULL, clear the respective list
1674         if (!vertexstring)
1675                 vertstrings_count = 0;
1676         if (!geometrystring)
1677                 geomstrings_count = 0;
1678         if (!fragmentstring)
1679                 fragstrings_count = 0;
1680
1681         vertstring_length = 0;
1682         for (i = 0;i < vertstrings_count;i++)
1683                 vertstring_length += strlen(vertstrings_list[i]);
1684         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1687
1688         geomstring_length = 0;
1689         for (i = 0;i < geomstrings_count;i++)
1690                 geomstring_length += strlen(geomstrings_list[i]);
1691         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1694
1695         fragstring_length = 0;
1696         for (i = 0;i < fragstrings_count;i++)
1697                 fragstring_length += strlen(fragstrings_list[i]);
1698         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1701
1702         // try to load the cached shader, or generate one
1703         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1704
1705         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1707         else
1708                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1709
1710         // free the strings
1711         if (vertstring)
1712                 Mem_Free(vertstring);
1713         if (geomstring)
1714                 Mem_Free(geomstring);
1715         if (fragstring)
1716                 Mem_Free(fragstring);
1717         if (vertexstring)
1718                 Mem_Free(vertexstring);
1719         if (geometrystring)
1720                 Mem_Free(geometrystring);
1721         if (fragmentstring)
1722                 Mem_Free(fragmentstring);
1723 }
1724
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 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);}
1728 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);}
1729 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);}
1730 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);}
1731
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1740 {
1741         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742         if (r_hlsl_permutation != perm)
1743         {
1744                 r_hlsl_permutation = perm;
1745                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                 {
1747                         if (!r_hlsl_permutation->compiled)
1748                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1749                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1750                         {
1751                                 // remove features until we find a valid permutation
1752                                 int i;
1753                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1754                                 {
1755                                         // reduce i more quickly whenever it would not remove any bits
1756                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757                                         if (!(permutation & j))
1758                                                 continue;
1759                                         permutation -= j;
1760                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761                                         if (!r_hlsl_permutation->compiled)
1762                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1764                                                 break;
1765                                 }
1766                                 if (i >= SHADERPERMUTATION_COUNT)
1767                                 {
1768                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770                                         return; // no bit left to clear, entire mode is broken
1771                                 }
1772                         }
1773                 }
1774                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1776         }
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1780 }
1781 #endif
1782
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1784 {
1785         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1789 }
1790
1791 void R_GLSL_Restart_f(void)
1792 {
1793         unsigned int i, limit;
1794         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795                 Mem_Free(glslshaderstring);
1796         glslshaderstring = NULL;
1797         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798                 Mem_Free(hlslshaderstring);
1799         hlslshaderstring = NULL;
1800         switch(vid.renderpath)
1801         {
1802         case RENDERPATH_D3D9:
1803 #ifdef SUPPORTD3D
1804                 {
1805                         r_hlsl_permutation_t *p;
1806                         r_hlsl_permutation = NULL;
1807                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808                         for (i = 0;i < limit;i++)
1809                         {
1810                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1811                                 {
1812                                         if (p->vertexshader)
1813                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1814                                         if (p->pixelshader)
1815                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1816                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1817                                 }
1818                         }
1819                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1820                 }
1821 #endif
1822                 break;
1823         case RENDERPATH_D3D10:
1824                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_D3D11:
1827                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1828                 break;
1829         case RENDERPATH_GL20:
1830         case RENDERPATH_GLES2:
1831                 {
1832                         r_glsl_permutation_t *p;
1833                         r_glsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1838                                 {
1839                                         GL_Backend_FreeProgram(p->program);
1840                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1844                 }
1845                 break;
1846         case RENDERPATH_GL11:
1847         case RENDERPATH_GL13:
1848         case RENDERPATH_GLES1:
1849                 break;
1850         case RENDERPATH_SOFT:
1851                 break;
1852         }
1853 }
1854
1855 void R_GLSL_DumpShader_f(void)
1856 {
1857         int i;
1858         qfile_t *file;
1859
1860         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1861         if (file)
1862         {
1863                 FS_Print(file, "/* The engine may define the following macros:\n");
1864                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1865                 for (i = 0;i < SHADERMODE_COUNT;i++)
1866                         FS_Print(file, glslshadermodeinfo[i].pretext);
1867                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1868                         FS_Print(file, shaderpermutationinfo[i].pretext);
1869                 FS_Print(file, "*/\n");
1870                 FS_Print(file, builtinshaderstring);
1871                 FS_Close(file);
1872                 Con_Printf("glsl/default.glsl written\n");
1873         }
1874         else
1875                 Con_Printf("failed to write to glsl/default.glsl\n");
1876
1877         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1878         if (file)
1879         {
1880                 FS_Print(file, "/* The engine may define the following macros:\n");
1881                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1882                 for (i = 0;i < SHADERMODE_COUNT;i++)
1883                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1884                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885                         FS_Print(file, shaderpermutationinfo[i].pretext);
1886                 FS_Print(file, "*/\n");
1887                 FS_Print(file, builtinhlslshaderstring);
1888                 FS_Close(file);
1889                 Con_Printf("hlsl/default.hlsl written\n");
1890         }
1891         else
1892                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1893 }
1894
1895 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1896 {
1897         if (!second)
1898                 texturemode = GL_MODULATE;
1899         switch (vid.renderpath)
1900         {
1901         case RENDERPATH_D3D9:
1902 #ifdef SUPPORTD3D
1903                 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))));
1904                 R_Mesh_TexBind(GL20TU_FIRST , first );
1905                 R_Mesh_TexBind(GL20TU_SECOND, second);
1906 #endif
1907                 break;
1908         case RENDERPATH_D3D10:
1909                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910                 break;
1911         case RENDERPATH_D3D11:
1912                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1913                 break;
1914         case RENDERPATH_GL20:
1915         case RENDERPATH_GLES2:
1916                 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))));
1917                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1918                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1919                 break;
1920         case RENDERPATH_GL13:
1921         case RENDERPATH_GLES1:
1922                 R_Mesh_TexBind(0, first );
1923                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1924                 R_Mesh_TexBind(1, second);
1925                 if (second)
1926                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1927                 break;
1928         case RENDERPATH_GL11:
1929                 R_Mesh_TexBind(0, first );
1930                 break;
1931         case RENDERPATH_SOFT:
1932                 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))));
1933                 R_Mesh_TexBind(GL20TU_FIRST , first );
1934                 R_Mesh_TexBind(GL20TU_SECOND, second);
1935                 break;
1936         }
1937 }
1938
1939 void R_SetupShader_DepthOrShadow(void)
1940 {
1941         switch (vid.renderpath)
1942         {
1943         case RENDERPATH_D3D9:
1944 #ifdef SUPPORTD3D
1945                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 #endif
1947                 break;
1948         case RENDERPATH_D3D10:
1949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950                 break;
1951         case RENDERPATH_D3D11:
1952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_GL20:
1955         case RENDERPATH_GLES2:
1956                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1957                 break;
1958         case RENDERPATH_GL13:
1959         case RENDERPATH_GLES1:
1960                 R_Mesh_TexBind(0, 0);
1961                 R_Mesh_TexBind(1, 0);
1962                 break;
1963         case RENDERPATH_GL11:
1964                 R_Mesh_TexBind(0, 0);
1965                 break;
1966         case RENDERPATH_SOFT:
1967                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1968                 break;
1969         }
1970 }
1971
1972 void R_SetupShader_ShowDepth(void)
1973 {
1974         switch (vid.renderpath)
1975         {
1976         case RENDERPATH_D3D9:
1977 #ifdef SUPPORTHLSL
1978                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1979 #endif
1980                 break;
1981         case RENDERPATH_D3D10:
1982                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_D3D11:
1985                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_GL20:
1988         case RENDERPATH_GLES2:
1989                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1990                 break;
1991         case RENDERPATH_GL13:
1992         case RENDERPATH_GLES1:
1993                 break;
1994         case RENDERPATH_GL11:
1995                 break;
1996         case RENDERPATH_SOFT:
1997                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1998                 break;
1999         }
2000 }
2001
2002 extern qboolean r_shadow_usingdeferredprepass;
2003 extern cvar_t r_shadow_deferred_8bitrange;
2004 extern rtexture_t *r_shadow_attenuationgradienttexture;
2005 extern rtexture_t *r_shadow_attenuation2dtexture;
2006 extern rtexture_t *r_shadow_attenuation3dtexture;
2007 extern qboolean r_shadow_usingshadowmap2d;
2008 extern qboolean r_shadow_usingshadowmaportho;
2009 extern float r_shadow_shadowmap_texturescale[2];
2010 extern float r_shadow_shadowmap_parameters[4];
2011 extern qboolean r_shadow_shadowmapvsdct;
2012 extern qboolean r_shadow_shadowmapsampler;
2013 extern int r_shadow_shadowmappcf;
2014 extern rtexture_t *r_shadow_shadowmap2dtexture;
2015 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2016 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2017 extern matrix4x4_t r_shadow_shadowmapmatrix;
2018 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2019 extern int r_shadow_prepass_width;
2020 extern int r_shadow_prepass_height;
2021 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2022 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2024 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2025 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2026
2027 #define BLENDFUNC_ALLOWS_COLORMOD      1
2028 #define BLENDFUNC_ALLOWS_FOG           2
2029 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2030 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2031 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2032 static int R_BlendFuncFlags(int src, int dst)
2033 {
2034         int r = 0;
2035
2036         // a blendfunc allows colormod if:
2037         // a) it can never keep the destination pixel invariant, or
2038         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2039         // this is to prevent unintended side effects from colormod
2040
2041         // a blendfunc allows fog if:
2042         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2043         // this is to prevent unintended side effects from fog
2044
2045         // these checks are the output of fogeval.pl
2046
2047         r |= BLENDFUNC_ALLOWS_COLORMOD;
2048         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2049         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2050         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2054         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2057         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2058         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2060         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2061         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2064         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069
2070         return r;
2071 }
2072
2073 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)
2074 {
2075         // select a permutation of the lighting shader appropriate to this
2076         // combination of texture, entity, light source, and fogging, only use the
2077         // minimum features necessary to avoid wasting rendering time in the
2078         // fragment shader on features that are not being used
2079         unsigned int permutation = 0;
2080         unsigned int mode = 0;
2081         int blendfuncflags;
2082         static float dummy_colormod[3] = {1, 1, 1};
2083         float *colormod = rsurface.colormod;
2084         float m16f[16];
2085         matrix4x4_t tempmatrix;
2086         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2087         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2088                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2089         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2090                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2091         if (rsurfacepass == RSURFPASS_BACKGROUND)
2092         {
2093                 // distorted background
2094                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2095                 {
2096                         mode = SHADERMODE_WATER;
2097                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2098                         {
2099                                 // this is the right thing to do for wateralpha
2100                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2101                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2102                         }
2103                         else
2104                         {
2105                                 // this is the right thing to do for entity alpha
2106                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2107                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2108                         }
2109                 }
2110                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2111                 {
2112                         mode = SHADERMODE_REFRACTION;
2113                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115                 }
2116                 else
2117                 {
2118                         mode = SHADERMODE_GENERIC;
2119                         permutation |= SHADERPERMUTATION_DIFFUSE;
2120                         GL_BlendFunc(GL_ONE, GL_ZERO);
2121                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2122                 }
2123         }
2124         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2125         {
2126                 if (r_glsl_offsetmapping.integer)
2127                 {
2128                         switch(rsurface.texture->offsetmapping)
2129                         {
2130                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2131                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2132                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2133                         case OFFSETMAPPING_OFF: break;
2134                         }
2135                 }
2136                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2137                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2138                 // normalmap (deferred prepass), may use alpha test on diffuse
2139                 mode = SHADERMODE_DEFERREDGEOMETRY;
2140                 GL_BlendFunc(GL_ONE, GL_ZERO);
2141                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2142         }
2143         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2144         {
2145                 if (r_glsl_offsetmapping.integer)
2146                 {
2147                         switch(rsurface.texture->offsetmapping)
2148                         {
2149                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2150                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2151                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2152                         case OFFSETMAPPING_OFF: break;
2153                         }
2154                 }
2155                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2157                 // light source
2158                 mode = SHADERMODE_LIGHTSOURCE;
2159                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2160                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2161                 if (diffusescale > 0)
2162                         permutation |= SHADERPERMUTATION_DIFFUSE;
2163                 if (specularscale > 0)
2164                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2165                 if (r_refdef.fogenabled)
2166                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2167                 if (rsurface.texture->colormapping)
2168                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2169                 if (r_shadow_usingshadowmap2d)
2170                 {
2171                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2172                         if(r_shadow_shadowmapvsdct)
2173                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2174
2175                         if (r_shadow_shadowmapsampler)
2176                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2177                         if (r_shadow_shadowmappcf > 1)
2178                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2179                         else if (r_shadow_shadowmappcf)
2180                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2181                 }
2182                 if (rsurface.texture->reflectmasktexture)
2183                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2184                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2185                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2186         }
2187         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer)
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 // unshaded geometry (fullbright or ambient model lighting)
2202                 mode = SHADERMODE_FLATCOLOR;
2203                 ambientscale = diffusescale = specularscale = 0;
2204                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2205                         permutation |= SHADERPERMUTATION_GLOW;
2206                 if (r_refdef.fogenabled)
2207                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2208                 if (rsurface.texture->colormapping)
2209                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2210                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2211                 {
2212                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2213                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214
2215                         if (r_shadow_shadowmapsampler)
2216                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2217                         if (r_shadow_shadowmappcf > 1)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2219                         else if (r_shadow_shadowmappcf)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2221                 }
2222                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2223                         permutation |= SHADERPERMUTATION_REFLECTION;
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2228         }
2229         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2230         {
2231                 if (r_glsl_offsetmapping.integer)
2232                 {
2233                         switch(rsurface.texture->offsetmapping)
2234                         {
2235                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238                         case OFFSETMAPPING_OFF: break;
2239                         }
2240                 }
2241                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243                 // directional model lighting
2244                 mode = SHADERMODE_LIGHTDIRECTION;
2245                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2246                         permutation |= SHADERPERMUTATION_GLOW;
2247                 permutation |= SHADERPERMUTATION_DIFFUSE;
2248                 if (specularscale > 0)
2249                         permutation |= SHADERPERMUTATION_SPECULAR;
2250                 if (r_refdef.fogenabled)
2251                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2252                 if (rsurface.texture->colormapping)
2253                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2254                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2255                 {
2256                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2257                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2258
2259                         if (r_shadow_shadowmapsampler)
2260                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2261                         if (r_shadow_shadowmappcf > 1)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2263                         else if (r_shadow_shadowmappcf)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2267                         permutation |= SHADERPERMUTATION_REFLECTION;
2268                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2269                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 if (r_shadow_bouncegridtexture)
2273                 {
2274                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2275                         if (r_shadow_bouncegriddirectional)
2276                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2277                 }
2278                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280         }
2281         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2282         {
2283                 if (r_glsl_offsetmapping.integer)
2284                 {
2285                         switch(rsurface.texture->offsetmapping)
2286                         {
2287                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_OFF: break;
2291                         }
2292                 }
2293                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295                 // ambient model lighting
2296                 mode = SHADERMODE_LIGHTDIRECTION;
2297                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2298                         permutation |= SHADERPERMUTATION_GLOW;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329         }
2330         else
2331         {
2332                 if (r_glsl_offsetmapping.integer)
2333                 {
2334                         switch(rsurface.texture->offsetmapping)
2335                         {
2336                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2337                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2338                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2339                         case OFFSETMAPPING_OFF: break;
2340                         }
2341                 }
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2343                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2344                 // lightmapped wall
2345                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346                         permutation |= SHADERPERMUTATION_GLOW;
2347                 if (r_refdef.fogenabled)
2348                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349                 if (rsurface.texture->colormapping)
2350                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2351                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352                 {
2353                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355
2356                         if (r_shadow_shadowmapsampler)
2357                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2358                         if (r_shadow_shadowmappcf > 1)
2359                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2360                         else if (r_shadow_shadowmappcf)
2361                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (FAKELIGHT_ENABLED)
2370                 {
2371                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2372                         mode = SHADERMODE_FAKELIGHT;
2373                         permutation |= SHADERPERMUTATION_DIFFUSE;
2374                         if (specularscale > 0)
2375                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2376                 }
2377                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2378                 {
2379                         // deluxemapping (light direction texture)
2380                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2381                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2382                         else
2383                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2384                         permutation |= SHADERPERMUTATION_DIFFUSE;
2385                         if (specularscale > 0)
2386                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2387                 }
2388                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2389                 {
2390                         // fake deluxemapping (uniform light direction in tangentspace)
2391                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392                         permutation |= SHADERPERMUTATION_DIFFUSE;
2393                         if (specularscale > 0)
2394                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395                 }
2396                 else if (rsurface.uselightmaptexture)
2397                 {
2398                         // ordinary lightmapping (q1bsp, q3bsp)
2399                         mode = SHADERMODE_LIGHTMAP;
2400                 }
2401                 else
2402                 {
2403                         // ordinary vertex coloring (q3bsp)
2404                         mode = SHADERMODE_VERTEXCOLOR;
2405                 }
2406                 if (r_shadow_bouncegridtexture)
2407                 {
2408                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2409                         if (r_shadow_bouncegriddirectional)
2410                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2411                 }
2412                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414         }
2415         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2416                 colormod = dummy_colormod;
2417         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2418                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2419         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2420                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2421         switch(vid.renderpath)
2422         {
2423         case RENDERPATH_D3D9:
2424 #ifdef SUPPORTD3D
2425                 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);
2426                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2427                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2428                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2429                 if (mode == SHADERMODE_LIGHTSOURCE)
2430                 {
2431                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2432                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2433                 }
2434                 else
2435                 {
2436                         if (mode == SHADERMODE_LIGHTDIRECTION)
2437                         {
2438                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2439                         }
2440                 }
2441                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2442                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2443                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2444                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2445                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2446
2447                 if (mode == SHADERMODE_LIGHTSOURCE)
2448                 {
2449                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2450                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2451                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2452                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2453                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2454
2455                         // additive passes are only darkened by fog, not tinted
2456                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2457                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2458                 }
2459                 else
2460                 {
2461                         if (mode == SHADERMODE_FLATCOLOR)
2462                         {
2463                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2464                         }
2465                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2466                         {
2467                                 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]);
2468                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2469                                 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);
2470                                 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);
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2472                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2474                         }
2475                         else
2476                         {
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2479                                 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);
2480                                 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);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2482                         }
2483                         // additive passes are only darkened by fog, not tinted
2484                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2486                         else
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2488                         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);
2489                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2490                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2491                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2492                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2493                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2494                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2495                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2496                         if (mode == SHADERMODE_WATER)
2497                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2498                 }
2499                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2500                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2501                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2502                 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));
2503                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2504                 if (rsurface.texture->pantstexture)
2505                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2506                 else
2507                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2508                 if (rsurface.texture->shirttexture)
2509                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2510                 else
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2512                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2513                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2514                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2515                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2516                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2517                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2518                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2519                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2520                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2521                         );
2522                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2523                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2524
2525                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2526                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2527                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2528                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2529                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2530                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2531                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2532                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2533                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2534                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2535                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2536                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2537                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2538                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2539                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2540                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2541                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2542                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2543                 {
2544                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2545                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2546                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2547                 }
2548                 else
2549                 {
2550                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2551                 }
2552 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2553 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2554                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2555                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2556                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2557                 {
2558                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2559                         if (rsurface.rtlight)
2560                         {
2561                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2562                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2563                         }
2564                 }
2565 #endif
2566                 break;
2567         case RENDERPATH_D3D10:
2568                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2569                 break;
2570         case RENDERPATH_D3D11:
2571                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572                 break;
2573         case RENDERPATH_GL20:
2574         case RENDERPATH_GLES2:
2575                 if (!vid.useinterleavedarrays)
2576                 {
2577                         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);
2578                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2579                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2580                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2581                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2582                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2584                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2585                 }
2586                 else
2587                 {
2588                         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);
2589                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2590                 }
2591                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2592                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2593                 if (mode == SHADERMODE_LIGHTSOURCE)
2594                 {
2595                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2596                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2597                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2598                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2599                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2600                         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);
2601         
2602                         // additive passes are only darkened by fog, not tinted
2603                         if (r_glsl_permutation->loc_FogColor >= 0)
2604                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2605                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606                 }
2607                 else
2608                 {
2609                         if (mode == SHADERMODE_FLATCOLOR)
2610                         {
2611                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2612                         }
2613                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2614                         {
2615                                 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]);
2616                                 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]);
2617                                 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);
2618                                 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);
2619                                 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);
2620                                 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]);
2621                                 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]);
2622                         }
2623                         else
2624                         {
2625                                 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]);
2626                                 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]);
2627                                 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);
2628                                 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);
2629                                 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);
2630                         }
2631                         // additive passes are only darkened by fog, not tinted
2632                         if (r_glsl_permutation->loc_FogColor >= 0)
2633                         {
2634                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2635                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2636                                 else
2637                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2638                         }
2639                         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);
2640                         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]);
2641                         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]);
2642                         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]);
2643                         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]);
2644                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2645                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2646                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2647                         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]);
2648                 }
2649                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2650                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2651                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2652                 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]);
2653                 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]);
2654
2655                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2656                 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));
2657                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2658                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2659                 {
2660                         if (rsurface.texture->pantstexture)
2661                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2662                         else
2663                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2664                 }
2665                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2666                 {
2667                         if (rsurface.texture->shirttexture)
2668                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2669                         else
2670                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2671                 }
2672                 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]);
2673                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2674                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2675                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2676                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2677                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2678                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2680                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2681                         );
2682                 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]);
2683                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2684                 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);}
2685                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2686
2687                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2688                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2689                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2690                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2691                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2692                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2693                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2694                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2695                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2696                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2697                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2698                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2699                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2700                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2701                 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);
2702                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2703                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2704                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2705                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2706                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2707                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2708                 {
2709                         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);
2710                         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);
2711                         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);
2712                 }
2713                 else
2714                 {
2715                         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);
2716                 }
2717                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2718                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2719                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2720                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2721                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2722                 {
2723                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2724                         if (rsurface.rtlight)
2725                         {
2726                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2727                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2728                         }
2729                 }
2730                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2731                 CHECKGLERROR
2732                 break;
2733         case RENDERPATH_GL11:
2734         case RENDERPATH_GL13:
2735         case RENDERPATH_GLES1:
2736                 break;
2737         case RENDERPATH_SOFT:
2738                 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);
2739                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2740                 R_SetupShader_SetPermutationSoft(mode, permutation);
2741                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2742                 if (mode == SHADERMODE_LIGHTSOURCE)
2743                 {
2744                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2746                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2747                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2748                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2749                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2750         
2751                         // additive passes are only darkened by fog, not tinted
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2753                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2754                 }
2755                 else
2756                 {
2757                         if (mode == SHADERMODE_FLATCOLOR)
2758                         {
2759                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2760                         }
2761                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2762                         {
2763                                 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]);
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2765                                 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);
2766                                 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);
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2768                                 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]);
2769                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2770                         }
2771                         else
2772                         {
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2775                                 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);
2776                                 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);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2778                         }
2779                         // additive passes are only darkened by fog, not tinted
2780                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2782                         else
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2784                         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);
2785                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2786                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2787                         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]);
2788                         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]);
2789                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2790                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2791                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2792                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2793                 }
2794                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2795                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2796                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2797                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2798                 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]);
2799
2800                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2801                 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));
2802                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2803                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2804                 {
2805                         if (rsurface.texture->pantstexture)
2806                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2807                         else
2808                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2809                 }
2810                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2811                 {
2812                         if (rsurface.texture->shirttexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2816                 }
2817                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2818                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2819                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2820                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2821                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2822                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2823                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2824                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2825                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2826                         );
2827                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2828                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2829
2830                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2831                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2832                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2833                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2834                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2835                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2836                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2837                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2838                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2839                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2840                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2841                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2842                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2843                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2844                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2845                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2846                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2847                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2848                 {
2849                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2850                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2851                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2852                 }
2853                 else
2854                 {
2855                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2856                 }
2857 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2858 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2859                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2860                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2861                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2862                 {
2863                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2864                         if (rsurface.rtlight)
2865                         {
2866                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2867                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2868                         }
2869                 }
2870                 break;
2871         }
2872 }
2873
2874 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2875 {
2876         // select a permutation of the lighting shader appropriate to this
2877         // combination of texture, entity, light source, and fogging, only use the
2878         // minimum features necessary to avoid wasting rendering time in the
2879         // fragment shader on features that are not being used
2880         unsigned int permutation = 0;
2881         unsigned int mode = 0;
2882         const float *lightcolorbase = rtlight->currentcolor;
2883         float ambientscale = rtlight->ambientscale;
2884         float diffusescale = rtlight->diffusescale;
2885         float specularscale = rtlight->specularscale;
2886         // this is the location of the light in view space
2887         vec3_t viewlightorigin;
2888         // this transforms from view space (camera) to light space (cubemap)
2889         matrix4x4_t viewtolight;
2890         matrix4x4_t lighttoview;
2891         float viewtolight16f[16];
2892         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2893         // light source
2894         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2895         if (rtlight->currentcubemap != r_texture_whitecube)
2896                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2897         if (diffusescale > 0)
2898                 permutation |= SHADERPERMUTATION_DIFFUSE;
2899         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2900                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2901         if (r_shadow_usingshadowmap2d)
2902         {
2903                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2904                 if (r_shadow_shadowmapvsdct)
2905                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2906
2907                 if (r_shadow_shadowmapsampler)
2908                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2909                 if (r_shadow_shadowmappcf > 1)
2910                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2911                 else if (r_shadow_shadowmappcf)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2913         }
2914         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2915         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2916         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2917         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2918         switch(vid.renderpath)
2919         {
2920         case RENDERPATH_D3D9:
2921 #ifdef SUPPORTD3D
2922                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2923                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2924                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2925                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2926                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2928                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2929                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2930                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2931                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2932                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2933
2934                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2935                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2936                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2937                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2938                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2939                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2940 #endif
2941                 break;
2942         case RENDERPATH_D3D10:
2943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2944                 break;
2945         case RENDERPATH_D3D11:
2946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2947                 break;
2948         case RENDERPATH_GL20:
2949         case RENDERPATH_GLES2:
2950                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2951                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2952                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2953                 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);
2954                 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);
2955                 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);
2956                 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]);
2957                 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]);
2958                 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));
2959                 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]);
2960                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2961
2962                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2963                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2964                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2965                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2966                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2967                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2968                 break;
2969         case RENDERPATH_GL11:
2970         case RENDERPATH_GL13:
2971         case RENDERPATH_GLES1:
2972                 break;
2973         case RENDERPATH_SOFT:
2974                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2975                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2976                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2977                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2980                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2981                 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]);
2982                 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));
2983                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2984                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2985
2986                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2987                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2988                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2989                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2990                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2991                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2992                 break;
2993         }
2994 }
2995
2996 #define SKINFRAME_HASH 1024
2997
2998 typedef struct
2999 {
3000         int loadsequence; // incremented each level change
3001         memexpandablearray_t array;
3002         skinframe_t *hash[SKINFRAME_HASH];
3003 }
3004 r_skinframe_t;
3005 r_skinframe_t r_skinframe;
3006
3007 void R_SkinFrame_PrepareForPurge(void)
3008 {
3009         r_skinframe.loadsequence++;
3010         // wrap it without hitting zero
3011         if (r_skinframe.loadsequence >= 200)
3012                 r_skinframe.loadsequence = 1;
3013 }
3014
3015 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3016 {
3017         if (!skinframe)
3018                 return;
3019         // mark the skinframe as used for the purging code
3020         skinframe->loadsequence = r_skinframe.loadsequence;
3021 }
3022
3023 void R_SkinFrame_Purge(void)
3024 {
3025         int i;
3026         skinframe_t *s;
3027         for (i = 0;i < SKINFRAME_HASH;i++)
3028         {
3029                 for (s = r_skinframe.hash[i];s;s = s->next)
3030                 {
3031                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3032                         {
3033                                 if (s->merged == s->base)
3034                                         s->merged = NULL;
3035                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3036                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3037                                 R_PurgeTexture(s->merged);s->merged = NULL;
3038                                 R_PurgeTexture(s->base  );s->base   = NULL;
3039                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3040                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3041                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3042                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3043                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3044                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3045                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3046                                 s->loadsequence = 0;
3047                         }
3048                 }
3049         }
3050 }
3051
3052 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3053         skinframe_t *item;
3054         char basename[MAX_QPATH];
3055
3056         Image_StripImageExtension(name, basename, sizeof(basename));
3057
3058         if( last == NULL ) {
3059                 int hashindex;
3060                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3061                 item = r_skinframe.hash[hashindex];
3062         } else {
3063                 item = last->next;
3064         }
3065
3066         // linearly search through the hash bucket
3067         for( ; item ; item = item->next ) {
3068                 if( !strcmp( item->basename, basename ) ) {
3069                         return item;
3070                 }
3071         }
3072         return NULL;
3073 }
3074
3075 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3076 {
3077         skinframe_t *item;
3078         int hashindex;
3079         char basename[MAX_QPATH];
3080
3081         Image_StripImageExtension(name, basename, sizeof(basename));
3082
3083         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3084         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3085                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3086                         break;
3087
3088         if (!item) {
3089                 rtexture_t *dyntexture;
3090                 // check whether its a dynamic texture
3091                 dyntexture = CL_GetDynTexture( basename );
3092                 if (!add && !dyntexture)
3093                         return NULL;
3094                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3095                 memset(item, 0, sizeof(*item));
3096                 strlcpy(item->basename, basename, sizeof(item->basename));
3097                 item->base = dyntexture; // either NULL or dyntexture handle
3098                 item->textureflags = textureflags;
3099                 item->comparewidth = comparewidth;
3100                 item->compareheight = compareheight;
3101                 item->comparecrc = comparecrc;
3102                 item->next = r_skinframe.hash[hashindex];
3103                 r_skinframe.hash[hashindex] = item;
3104         }
3105         else if( item->base == NULL )
3106         {
3107                 rtexture_t *dyntexture;
3108                 // check whether its a dynamic texture
3109                 // 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]
3110                 dyntexture = CL_GetDynTexture( basename );
3111                 item->base = dyntexture; // either NULL or dyntexture handle
3112         }
3113
3114         R_SkinFrame_MarkUsed(item);
3115         return item;
3116 }
3117
3118 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3119         { \
3120                 unsigned long long avgcolor[5], wsum; \
3121                 int pix, comp, w; \
3122                 avgcolor[0] = 0; \
3123                 avgcolor[1] = 0; \
3124                 avgcolor[2] = 0; \
3125                 avgcolor[3] = 0; \
3126                 avgcolor[4] = 0; \
3127                 wsum = 0; \
3128                 for(pix = 0; pix < cnt; ++pix) \
3129                 { \
3130                         w = 0; \
3131                         for(comp = 0; comp < 3; ++comp) \
3132                                 w += getpixel; \
3133                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3134                         { \
3135                                 ++wsum; \
3136                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3137                                 w = getpixel; \
3138                                 for(comp = 0; comp < 3; ++comp) \
3139                                         avgcolor[comp] += getpixel * w; \
3140                                 avgcolor[3] += w; \
3141                         } \
3142                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3143                         avgcolor[4] += getpixel; \
3144                 } \
3145                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3146                         avgcolor[3] = 1; \
3147                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3148                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3149                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3150                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3151         }
3152
3153 extern cvar_t gl_picmip;
3154 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3155 {
3156         int j;
3157         unsigned char *pixels;
3158         unsigned char *bumppixels;
3159         unsigned char *basepixels = NULL;
3160         int basepixels_width = 0;
3161         int basepixels_height = 0;
3162         skinframe_t *skinframe;
3163         rtexture_t *ddsbase = NULL;
3164         qboolean ddshasalpha = false;
3165         float ddsavgcolor[4];
3166         char basename[MAX_QPATH];
3167         int miplevel = R_PicmipForFlags(textureflags);
3168         int savemiplevel = miplevel;
3169         int mymiplevel;
3170
3171         if (cls.state == ca_dedicated)
3172                 return NULL;
3173
3174         // return an existing skinframe if already loaded
3175         // if loading of the first image fails, don't make a new skinframe as it
3176         // would cause all future lookups of this to be missing
3177         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3178         if (skinframe && skinframe->base)
3179                 return skinframe;
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         // check for DDS texture file first
3184         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3185         {
3186                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3187                 if (basepixels == NULL)
3188                         return NULL;
3189         }
3190
3191         // FIXME handle miplevel
3192
3193         if (developer_loading.integer)
3194                 Con_Printf("loading skin \"%s\"\n", name);
3195
3196         // we've got some pixels to store, so really allocate this new texture now
3197         if (!skinframe)
3198                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3199         skinframe->stain = NULL;
3200         skinframe->merged = NULL;
3201         skinframe->base = NULL;
3202         skinframe->pants = NULL;
3203         skinframe->shirt = NULL;
3204         skinframe->nmap = NULL;
3205         skinframe->gloss = NULL;
3206         skinframe->glow = NULL;
3207         skinframe->fog = NULL;
3208         skinframe->reflect = NULL;
3209         skinframe->hasalpha = false;
3210
3211         if (ddsbase)
3212         {
3213                 skinframe->base = ddsbase;
3214                 skinframe->hasalpha = ddshasalpha;
3215                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3216                 if (r_loadfog && skinframe->hasalpha)
3217                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3218                 //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]);
3219         }
3220         else
3221         {
3222                 basepixels_width = image_width;
3223                 basepixels_height = image_height;
3224                 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);
3225                 if (textureflags & TEXF_ALPHA)
3226                 {
3227                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3228                         {
3229                                 if (basepixels[j] < 255)
3230                                 {
3231                                         skinframe->hasalpha = true;
3232                                         break;
3233                                 }
3234                         }
3235                         if (r_loadfog && skinframe->hasalpha)
3236                         {
3237                                 // has transparent pixels
3238                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3239                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3240                                 {
3241                                         pixels[j+0] = 255;
3242                                         pixels[j+1] = 255;
3243                                         pixels[j+2] = 255;
3244                                         pixels[j+3] = basepixels[j+3];
3245                                 }
3246                                 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);
3247                                 Mem_Free(pixels);
3248                         }
3249                 }
3250                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3251                 //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]);
3252                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3253                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3254                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3255                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3256         }
3257
3258         if (r_loaddds)
3259         {
3260                 mymiplevel = savemiplevel;
3261                 if (r_loadnormalmap)
3262                         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);
3263                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3264                 if (r_loadgloss)
3265                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269         }
3270
3271         // _norm is the name used by tenebrae and has been adopted as standard
3272         if (r_loadnormalmap && skinframe->nmap == NULL)
3273         {
3274                 mymiplevel = savemiplevel;
3275                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3276                 {
3277                         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);
3278                         Mem_Free(pixels);
3279                         pixels = NULL;
3280                 }
3281                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3282                 {
3283                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3284                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3285                         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);
3286                         Mem_Free(pixels);
3287                         Mem_Free(bumppixels);
3288                 }
3289                 else if (r_shadow_bumpscale_basetexture.value > 0)
3290                 {
3291                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3292                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3293                         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);
3294                         Mem_Free(pixels);
3295                 }
3296                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3297                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3298         }
3299
3300         // _luma is supported only for tenebrae compatibility
3301         // _glow is the preferred name
3302         mymiplevel = savemiplevel;
3303         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))))
3304         {
3305                 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);
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3307                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3308                 Mem_Free(pixels);pixels = NULL;
3309         }
3310
3311         mymiplevel = savemiplevel;
3312         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3313         {
3314                 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);
3315                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3316                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3317                 Mem_Free(pixels);
3318                 pixels = NULL;
3319         }
3320
3321         mymiplevel = savemiplevel;
3322         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3323         {
3324                 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);
3325                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3326                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3327                 Mem_Free(pixels);
3328                 pixels = NULL;
3329         }
3330
3331         mymiplevel = savemiplevel;
3332         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3333         {
3334                 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);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3336                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3337                 Mem_Free(pixels);
3338                 pixels = NULL;
3339         }
3340
3341         mymiplevel = savemiplevel;
3342         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3343         {
3344                 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);
3345                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3346                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3347                 Mem_Free(pixels);
3348                 pixels = NULL;
3349         }
3350
3351         if (basepixels)
3352                 Mem_Free(basepixels);
3353
3354         return skinframe;
3355 }
3356
3357 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3358 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3359 {
3360         int i;
3361         unsigned char *temp1, *temp2;
3362         skinframe_t *skinframe;
3363
3364         if (cls.state == ca_dedicated)
3365                 return NULL;
3366
3367         // if already loaded just return it, otherwise make a new skinframe
3368         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3369         if (skinframe && skinframe->base)
3370                 return skinframe;
3371
3372         skinframe->stain = NULL;
3373         skinframe->merged = NULL;
3374         skinframe->base = NULL;
3375         skinframe->pants = NULL;
3376         skinframe->shirt = NULL;
3377         skinframe->nmap = NULL;
3378         skinframe->gloss = NULL;
3379         skinframe->glow = NULL;
3380         skinframe->fog = NULL;
3381         skinframe->reflect = NULL;
3382         skinframe->hasalpha = false;
3383
3384         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3385         if (!skindata)
3386                 return NULL;
3387
3388         if (developer_loading.integer)
3389                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3390
3391         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3392         {
3393                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3394                 temp2 = temp1 + width * height * 4;
3395                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3396                 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);
3397                 Mem_Free(temp1);
3398         }
3399         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3400         if (textureflags & TEXF_ALPHA)
3401         {
3402                 for (i = 3;i < width * height * 4;i += 4)
3403                 {
3404                         if (skindata[i] < 255)
3405                         {
3406                                 skinframe->hasalpha = true;
3407                                 break;
3408                         }
3409                 }
3410                 if (r_loadfog && skinframe->hasalpha)
3411                 {
3412                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3413                         memcpy(fogpixels, skindata, width * height * 4);
3414                         for (i = 0;i < width * height * 4;i += 4)
3415                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3416                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3417                         Mem_Free(fogpixels);
3418                 }
3419         }
3420
3421         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3422         //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]);
3423
3424         return skinframe;
3425 }
3426
3427 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3428 {
3429         int i;
3430         int featuresmask;
3431         skinframe_t *skinframe;
3432
3433         if (cls.state == ca_dedicated)
3434                 return NULL;
3435
3436         // if already loaded just return it, otherwise make a new skinframe
3437         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3438         if (skinframe && skinframe->base)
3439                 return skinframe;
3440
3441         skinframe->stain = NULL;
3442         skinframe->merged = NULL;
3443         skinframe->base = NULL;
3444         skinframe->pants = NULL;
3445         skinframe->shirt = NULL;
3446         skinframe->nmap = NULL;
3447         skinframe->gloss = NULL;
3448         skinframe->glow = NULL;
3449         skinframe->fog = NULL;
3450         skinframe->reflect = NULL;
3451         skinframe->hasalpha = false;
3452
3453         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3454         if (!skindata)
3455                 return NULL;
3456
3457         if (developer_loading.integer)
3458                 Con_Printf("loading quake skin \"%s\"\n", name);
3459
3460         // 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)
3461         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3462         memcpy(skinframe->qpixels, skindata, width*height);
3463         skinframe->qwidth = width;
3464         skinframe->qheight = height;
3465
3466         featuresmask = 0;
3467         for (i = 0;i < width * height;i++)
3468                 featuresmask |= palette_featureflags[skindata[i]];
3469
3470         skinframe->hasalpha = false;
3471         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3472         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3473         skinframe->qgeneratemerged = true;
3474         skinframe->qgeneratebase = skinframe->qhascolormapping;
3475         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3476
3477         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3478         //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]);
3479
3480         return skinframe;
3481 }
3482
3483 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3484 {
3485         int width;
3486         int height;
3487         unsigned char *skindata;
3488
3489         if (!skinframe->qpixels)
3490                 return;
3491
3492         if (!skinframe->qhascolormapping)
3493                 colormapped = false;
3494
3495         if (colormapped)
3496         {
3497                 if (!skinframe->qgeneratebase)
3498                         return;
3499         }
3500         else
3501         {
3502                 if (!skinframe->qgeneratemerged)
3503                         return;
3504         }
3505
3506         width = skinframe->qwidth;
3507         height = skinframe->qheight;
3508         skindata = skinframe->qpixels;
3509
3510         if (skinframe->qgeneratenmap)
3511         {
3512                 unsigned char *temp1, *temp2;
3513                 skinframe->qgeneratenmap = false;
3514                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3515                 temp2 = temp1 + width * height * 4;
3516                 // use either a custom palette or the quake palette
3517                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3518                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3519                 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);
3520                 Mem_Free(temp1);
3521         }
3522
3523         if (skinframe->qgenerateglow)
3524         {
3525                 skinframe->qgenerateglow = false;
3526                 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
3527         }
3528
3529         if (colormapped)
3530         {
3531                 skinframe->qgeneratebase = false;
3532                 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);
3533                 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);
3534                 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);
3535         }
3536         else
3537         {
3538                 skinframe->qgeneratemerged = false;
3539                 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);
3540         }
3541
3542         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3543         {
3544                 Mem_Free(skinframe->qpixels);
3545                 skinframe->qpixels = NULL;
3546         }
3547 }
3548
3549 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)
3550 {
3551         int i;
3552         skinframe_t *skinframe;
3553
3554         if (cls.state == ca_dedicated)
3555                 return NULL;
3556
3557         // if already loaded just return it, otherwise make a new skinframe
3558         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3559         if (skinframe && skinframe->base)
3560                 return skinframe;
3561
3562         skinframe->stain = NULL;
3563         skinframe->merged = NULL;
3564         skinframe->base = NULL;
3565         skinframe->pants = NULL;
3566         skinframe->shirt = NULL;
3567         skinframe->nmap = NULL;
3568         skinframe->gloss = NULL;
3569         skinframe->glow = NULL;
3570         skinframe->fog = NULL;
3571         skinframe->reflect = NULL;
3572         skinframe->hasalpha = false;
3573
3574         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3575         if (!skindata)
3576                 return NULL;
3577
3578         if (developer_loading.integer)
3579                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3580
3581         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3582         if (textureflags & TEXF_ALPHA)
3583         {
3584                 for (i = 0;i < width * height;i++)
3585                 {
3586                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3587                         {
3588                                 skinframe->hasalpha = true;
3589                                 break;
3590                         }
3591                 }
3592                 if (r_loadfog && skinframe->hasalpha)
3593                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3594         }
3595
3596         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3597         //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]);
3598
3599         return skinframe;
3600 }
3601
3602 skinframe_t *R_SkinFrame_LoadMissing(void)
3603 {
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3610         skinframe->stain = NULL;
3611         skinframe->merged = NULL;
3612         skinframe->base = NULL;
3613         skinframe->pants = NULL;
3614         skinframe->shirt = NULL;
3615         skinframe->nmap = NULL;
3616         skinframe->gloss = NULL;
3617         skinframe->glow = NULL;
3618         skinframe->fog = NULL;
3619         skinframe->reflect = NULL;
3620         skinframe->hasalpha = false;
3621
3622         skinframe->avgcolor[0] = rand() / RAND_MAX;
3623         skinframe->avgcolor[1] = rand() / RAND_MAX;
3624         skinframe->avgcolor[2] = rand() / RAND_MAX;
3625         skinframe->avgcolor[3] = 1;
3626
3627         return skinframe;
3628 }
3629
3630 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3631 typedef struct suffixinfo_s
3632 {
3633         const char *suffix;
3634         qboolean flipx, flipy, flipdiagonal;
3635 }
3636 suffixinfo_t;
3637 static suffixinfo_t suffix[3][6] =
3638 {
3639         {
3640                 {"px",   false, false, false},
3641                 {"nx",   false, false, false},
3642                 {"py",   false, false, false},
3643                 {"ny",   false, false, false},
3644                 {"pz",   false, false, false},
3645                 {"nz",   false, false, false}
3646         },
3647         {
3648                 {"posx", false, false, false},
3649                 {"negx", false, false, false},
3650                 {"posy", false, false, false},
3651                 {"negy", false, false, false},
3652                 {"posz", false, false, false},
3653                 {"negz", false, false, false}
3654         },
3655         {
3656                 {"rt",    true, false,  true},
3657                 {"lf",   false,  true,  true},
3658                 {"ft",    true,  true, false},
3659                 {"bk",   false, false, false},
3660                 {"up",    true, false,  true},
3661                 {"dn",    true, false,  true}
3662         }
3663 };
3664
3665 static int componentorder[4] = {0, 1, 2, 3};
3666
3667 rtexture_t *R_LoadCubemap(const char *basename)
3668 {
3669         int i, j, cubemapsize;
3670         unsigned char *cubemappixels, *image_buffer;
3671         rtexture_t *cubemaptexture;
3672         char name[256];
3673         // must start 0 so the first loadimagepixels has no requested width/height
3674         cubemapsize = 0;
3675         cubemappixels = NULL;
3676         cubemaptexture = NULL;
3677         // keep trying different suffix groups (posx, px, rt) until one loads
3678         for (j = 0;j < 3 && !cubemappixels;j++)
3679         {
3680                 // load the 6 images in the suffix group
3681                 for (i = 0;i < 6;i++)
3682                 {
3683                         // generate an image name based on the base and and suffix
3684                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3685                         // load it
3686                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3687                         {
3688                                 // an image loaded, make sure width and height are equal
3689                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3690                                 {
3691                                         // if this is the first image to load successfully, allocate the cubemap memory
3692                                         if (!cubemappixels && image_width >= 1)
3693                                         {
3694                                                 cubemapsize = image_width;
3695                                                 // note this clears to black, so unavailable sides are black
3696                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3697                                         }
3698                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3699                                         if (cubemappixels)
3700                                                 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);
3701                                 }
3702                                 else
3703                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3704                                 // free the image
3705                                 Mem_Free(image_buffer);
3706                         }
3707                 }
3708         }
3709         // if a cubemap loaded, upload it
3710         if (cubemappixels)
3711         {
3712                 if (developer_loading.integer)
3713                         Con_Printf("loading cubemap \"%s\"\n", basename);
3714
3715                 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);
3716                 Mem_Free(cubemappixels);
3717         }
3718         else
3719         {
3720                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3721                 if (developer_loading.integer)
3722                 {
3723                         Con_Printf("(tried tried images ");
3724                         for (j = 0;j < 3;j++)
3725                                 for (i = 0;i < 6;i++)
3726                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3727                         Con_Print(" and was unable to find any of them).\n");
3728                 }
3729         }
3730         return cubemaptexture;
3731 }
3732
3733 rtexture_t *R_GetCubemap(const char *basename)
3734 {
3735         int i;
3736         for (i = 0;i < r_texture_numcubemaps;i++)
3737                 if (r_texture_cubemaps[i] != NULL)
3738                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3739                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3740         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3741                 return r_texture_whitecube;
3742         r_texture_numcubemaps++;
3743         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3744         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3745         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3746         return r_texture_cubemaps[i]->texture;
3747 }
3748
3749 void R_FreeCubemap(const char *basename)
3750 {
3751         int i;
3752
3753         for (i = 0;i < r_texture_numcubemaps;i++)
3754         {
3755                 if (r_texture_cubemaps[i] != NULL)
3756                 {
3757                         if (r_texture_cubemaps[i]->texture)
3758                         {
3759                                 if (developer_loading.integer)
3760                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3761                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3762                                 Mem_Free(r_texture_cubemaps[i]);
3763                                 r_texture_cubemaps[i] = NULL;
3764                         }
3765                 }
3766         }
3767 }
3768
3769 void R_FreeCubemaps(void)
3770 {
3771         int i;
3772         for (i = 0;i < r_texture_numcubemaps;i++)
3773         {
3774                 if (developer_loading.integer)
3775                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3776                 if (r_texture_cubemaps[i] != NULL)
3777                 {
3778                         if (r_texture_cubemaps[i]->texture)
3779                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3780                         Mem_Free(r_texture_cubemaps[i]);
3781                 }
3782         }
3783         r_texture_numcubemaps = 0;
3784 }
3785
3786 void R_Main_FreeViewCache(void)
3787 {
3788         if (r_refdef.viewcache.entityvisible)
3789                 Mem_Free(r_refdef.viewcache.entityvisible);
3790         if (r_refdef.viewcache.world_pvsbits)
3791                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3792         if (r_refdef.viewcache.world_leafvisible)
3793                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3794         if (r_refdef.viewcache.world_surfacevisible)
3795                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3796         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3797 }
3798
3799 void R_Main_ResizeViewCache(void)
3800 {
3801         int numentities = r_refdef.scene.numentities;
3802         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3803         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3804         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3805         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3806         if (r_refdef.viewcache.maxentities < numentities)
3807         {
3808                 r_refdef.viewcache.maxentities = numentities;
3809                 if (r_refdef.viewcache.entityvisible)
3810                         Mem_Free(r_refdef.viewcache.entityvisible);
3811                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3812         }
3813         if (r_refdef.viewcache.world_numclusters != numclusters)
3814         {
3815                 r_refdef.viewcache.world_numclusters = numclusters;
3816                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3817                 if (r_refdef.viewcache.world_pvsbits)
3818                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3819                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3820         }
3821         if (r_refdef.viewcache.world_numleafs != numleafs)
3822         {
3823                 r_refdef.viewcache.world_numleafs = numleafs;
3824                 if (r_refdef.viewcache.world_leafvisible)
3825                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3826                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3827         }
3828         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3829         {
3830                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3831                 if (r_refdef.viewcache.world_surfacevisible)
3832                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3833                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3834         }
3835 }
3836
3837 extern rtexture_t *loadingscreentexture;
3838 void gl_main_start(void)
3839 {
3840         loadingscreentexture = NULL;
3841         r_texture_blanknormalmap = NULL;
3842         r_texture_white = NULL;
3843         r_texture_grey128 = NULL;
3844         r_texture_black = NULL;
3845         r_texture_whitecube = NULL;
3846         r_texture_normalizationcube = NULL;
3847         r_texture_fogattenuation = NULL;
3848         r_texture_fogheighttexture = NULL;
3849         r_texture_gammaramps = NULL;
3850         r_texture_numcubemaps = 0;
3851
3852         r_loaddds = r_texture_dds_load.integer != 0;
3853         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3854
3855         switch(vid.renderpath)
3856         {
3857         case RENDERPATH_GL20:
3858         case RENDERPATH_D3D9:
3859         case RENDERPATH_D3D10:
3860         case RENDERPATH_D3D11:
3861         case RENDERPATH_SOFT:
3862         case RENDERPATH_GLES2:
3863                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3864                 Cvar_SetValueQuick(&gl_combine, 1);
3865                 Cvar_SetValueQuick(&r_glsl, 1);
3866                 r_loadnormalmap = true;
3867                 r_loadgloss = true;
3868                 r_loadfog = false;
3869                 break;
3870         case RENDERPATH_GL13:
3871         case RENDERPATH_GLES1:
3872                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3873                 Cvar_SetValueQuick(&gl_combine, 1);
3874                 Cvar_SetValueQuick(&r_glsl, 0);
3875                 r_loadnormalmap = false;
3876                 r_loadgloss = false;
3877                 r_loadfog = true;
3878                 break;
3879         case RENDERPATH_GL11:
3880                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3881                 Cvar_SetValueQuick(&gl_combine, 0);
3882                 Cvar_SetValueQuick(&r_glsl, 0);
3883                 r_loadnormalmap = false;
3884                 r_loadgloss = false;
3885                 r_loadfog = true;
3886                 break;
3887         }
3888
3889         R_AnimCache_Free();
3890         R_FrameData_Reset();
3891
3892         r_numqueries = 0;
3893         r_maxqueries = 0;
3894         memset(r_queries, 0, sizeof(r_queries));
3895
3896         r_qwskincache = NULL;
3897         r_qwskincache_size = 0;
3898
3899         // due to caching of texture_t references, the collision cache must be reset
3900         Collision_Cache_Reset(true);
3901
3902         // set up r_skinframe loading system for textures
3903         memset(&r_skinframe, 0, sizeof(r_skinframe));
3904         r_skinframe.loadsequence = 1;
3905         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3906
3907         r_main_texturepool = R_AllocTexturePool();
3908         R_BuildBlankTextures();
3909         R_BuildNoTexture();
3910         if (vid.support.arb_texture_cube_map)
3911         {
3912                 R_BuildWhiteCube();
3913                 R_BuildNormalizationCube();
3914         }
3915         r_texture_fogattenuation = NULL;
3916         r_texture_fogheighttexture = NULL;
3917         r_texture_gammaramps = NULL;
3918         //r_texture_fogintensity = NULL;
3919         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3920         memset(&r_waterstate, 0, sizeof(r_waterstate));
3921         r_glsl_permutation = NULL;
3922         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3923         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3924         glslshaderstring = NULL;
3925 #ifdef SUPPORTD3D
3926         r_hlsl_permutation = NULL;
3927         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3928         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3929 #endif
3930         hlslshaderstring = NULL;
3931         memset(&r_svbsp, 0, sizeof (r_svbsp));
3932
3933         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3934         r_texture_numcubemaps = 0;
3935
3936         r_refdef.fogmasktable_density = 0;
3937 }
3938
3939 void gl_main_shutdown(void)
3940 {
3941         R_AnimCache_Free();
3942         R_FrameData_Reset();
3943
3944         R_Main_FreeViewCache();
3945
3946         switch(vid.renderpath)
3947         {
3948         case RENDERPATH_GL11:
3949         case RENDERPATH_GL13:
3950         case RENDERPATH_GL20:
3951         case RENDERPATH_GLES1:
3952         case RENDERPATH_GLES2:
3953                 if (r_maxqueries)
3954                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3955                 break;
3956         case RENDERPATH_D3D9:
3957                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3958                 break;
3959         case RENDERPATH_D3D10:
3960                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3961                 break;
3962         case RENDERPATH_D3D11:
3963                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3964                 break;
3965         case RENDERPATH_SOFT:
3966                 break;
3967         }
3968
3969         r_numqueries = 0;
3970         r_maxqueries = 0;
3971         memset(r_queries, 0, sizeof(r_queries));
3972
3973         r_qwskincache = NULL;
3974         r_qwskincache_size = 0;
3975
3976         // clear out the r_skinframe state
3977         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3978         memset(&r_skinframe, 0, sizeof(r_skinframe));
3979
3980         if (r_svbsp.nodes)
3981                 Mem_Free(r_svbsp.nodes);
3982         memset(&r_svbsp, 0, sizeof (r_svbsp));
3983         R_FreeTexturePool(&r_main_texturepool);
3984         loadingscreentexture = NULL;
3985         r_texture_blanknormalmap = NULL;
3986         r_texture_white = NULL;
3987         r_texture_grey128 = NULL;
3988         r_texture_black = NULL;
3989         r_texture_whitecube = NULL;
3990         r_texture_normalizationcube = NULL;
3991         r_texture_fogattenuation = NULL;
3992         r_texture_fogheighttexture = NULL;
3993         r_texture_gammaramps = NULL;
3994         r_texture_numcubemaps = 0;
3995         //r_texture_fogintensity = NULL;
3996         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3997         memset(&r_waterstate, 0, sizeof(r_waterstate));
3998         R_GLSL_Restart_f();
3999
4000         r_glsl_permutation = NULL;
4001         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4002         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4003         glslshaderstring = NULL;
4004 #ifdef SUPPORTD3D
4005         r_hlsl_permutation = NULL;
4006         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4007         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4008 #endif
4009         hlslshaderstring = NULL;
4010 }
4011
4012 extern void CL_ParseEntityLump(char *entitystring);
4013 void gl_main_newmap(void)
4014 {
4015         // FIXME: move this code to client
4016         char *entities, entname[MAX_QPATH];
4017         if (r_qwskincache)
4018                 Mem_Free(r_qwskincache);
4019         r_qwskincache = NULL;
4020         r_qwskincache_size = 0;
4021         if (cl.worldmodel)
4022         {
4023                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4024                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4025                 {
4026                         CL_ParseEntityLump(entities);
4027                         Mem_Free(entities);
4028                         return;
4029                 }
4030                 if (cl.worldmodel->brush.entities)
4031                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4032         }
4033         R_Main_FreeViewCache();
4034
4035         R_FrameData_Reset();
4036 }
4037
4038 void GL_Main_Init(void)
4039 {
4040         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4041
4042         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4043         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4044         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4045         if (gamemode == GAME_NEHAHRA)
4046         {
4047                 Cvar_RegisterVariable (&gl_fogenable);
4048                 Cvar_RegisterVariable (&gl_fogdensity);
4049                 Cvar_RegisterVariable (&gl_fogred);
4050                 Cvar_RegisterVariable (&gl_foggreen);
4051                 Cvar_RegisterVariable (&gl_fogblue);
4052                 Cvar_RegisterVariable (&gl_fogstart);
4053                 Cvar_RegisterVariable (&gl_fogend);
4054                 Cvar_RegisterVariable (&gl_skyclip);
4055         }
4056         Cvar_RegisterVariable(&r_motionblur);
4057         Cvar_RegisterVariable(&r_motionblur_maxblur);
4058         Cvar_RegisterVariable(&r_motionblur_bmin);
4059         Cvar_RegisterVariable(&r_motionblur_vmin);
4060         Cvar_RegisterVariable(&r_motionblur_vmax);
4061         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4062         Cvar_RegisterVariable(&r_motionblur_randomize);
4063         Cvar_RegisterVariable(&r_damageblur);
4064         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4065         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4066         Cvar_RegisterVariable(&r_equalize_entities_by);
4067         Cvar_RegisterVariable(&r_equalize_entities_to);
4068         Cvar_RegisterVariable(&r_depthfirst);
4069         Cvar_RegisterVariable(&r_useinfinitefarclip);
4070         Cvar_RegisterVariable(&r_farclip_base);
4071         Cvar_RegisterVariable(&r_farclip_world);
4072         Cvar_RegisterVariable(&r_nearclip);
4073         Cvar_RegisterVariable(&r_deformvertexes);
4074         Cvar_RegisterVariable(&r_transparent);
4075         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4076         Cvar_RegisterVariable(&r_showoverdraw);
4077         Cvar_RegisterVariable(&r_showbboxes);
4078         Cvar_RegisterVariable(&r_showsurfaces);
4079         Cvar_RegisterVariable(&r_showtris);
4080         Cvar_RegisterVariable(&r_shownormals);
4081         Cvar_RegisterVariable(&r_showlighting);
4082         Cvar_RegisterVariable(&r_showshadowvolumes);
4083         Cvar_RegisterVariable(&r_showcollisionbrushes);
4084         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4085         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4086         Cvar_RegisterVariable(&r_showdisabledepthtest);
4087         Cvar_RegisterVariable(&r_drawportals);
4088         Cvar_RegisterVariable(&r_drawentities);
4089         Cvar_RegisterVariable(&r_draw2d);
4090         Cvar_RegisterVariable(&r_drawworld);
4091         Cvar_RegisterVariable(&r_cullentities_trace);
4092         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4093         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4094         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4095         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4096         Cvar_RegisterVariable(&r_drawviewmodel);
4097         Cvar_RegisterVariable(&r_drawexteriormodel);
4098         Cvar_RegisterVariable(&r_speeds);
4099         Cvar_RegisterVariable(&r_fullbrights);
4100         Cvar_RegisterVariable(&r_wateralpha);
4101         Cvar_RegisterVariable(&r_dynamic);
4102         Cvar_RegisterVariable(&r_fakelight);
4103         Cvar_RegisterVariable(&r_fakelight_intensity);
4104         Cvar_RegisterVariable(&r_fullbright);
4105         Cvar_RegisterVariable(&r_shadows);
4106         Cvar_RegisterVariable(&r_shadows_darken);
4107         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4108         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4109         Cvar_RegisterVariable(&r_shadows_throwdistance);
4110         Cvar_RegisterVariable(&r_shadows_throwdirection);
4111         Cvar_RegisterVariable(&r_shadows_focus);
4112         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4113         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4114         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4115         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4116         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4117         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4118         Cvar_RegisterVariable(&r_fog_exp2);
4119         Cvar_RegisterVariable(&r_fog_clear);
4120         Cvar_RegisterVariable(&r_drawfog);
4121         Cvar_RegisterVariable(&r_transparentdepthmasking);
4122         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4123         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4124         Cvar_RegisterVariable(&r_texture_dds_load);
4125         Cvar_RegisterVariable(&r_texture_dds_save);
4126         Cvar_RegisterVariable(&r_textureunits);
4127         Cvar_RegisterVariable(&gl_combine);
4128         Cvar_RegisterVariable(&r_viewfbo);
4129         Cvar_RegisterVariable(&r_viewscale);
4130         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4131         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4132         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4133         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4134         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4135         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4136         Cvar_RegisterVariable(&r_glsl);
4137         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4138         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4139         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4140         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4141         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4142         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4143         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4144         Cvar_RegisterVariable(&r_glsl_postprocess);
4145         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4146         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4147         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4148         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4149         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4150         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4151         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4152         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4153
4154         Cvar_RegisterVariable(&r_water);
4155         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4156         Cvar_RegisterVariable(&r_water_clippingplanebias);
4157         Cvar_RegisterVariable(&r_water_refractdistort);
4158         Cvar_RegisterVariable(&r_water_reflectdistort);
4159         Cvar_RegisterVariable(&r_water_scissormode);
4160         Cvar_RegisterVariable(&r_water_lowquality);
4161
4162         Cvar_RegisterVariable(&r_lerpsprites);
4163         Cvar_RegisterVariable(&r_lerpmodels);
4164         Cvar_RegisterVariable(&r_lerplightstyles);
4165         Cvar_RegisterVariable(&r_waterscroll);
4166         Cvar_RegisterVariable(&r_bloom);
4167         Cvar_RegisterVariable(&r_bloom_colorscale);
4168         Cvar_RegisterVariable(&r_bloom_brighten);
4169         Cvar_RegisterVariable(&r_bloom_blur);
4170         Cvar_RegisterVariable(&r_bloom_resolution);
4171         Cvar_RegisterVariable(&r_bloom_colorexponent);
4172         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4173         Cvar_RegisterVariable(&r_hdr);
4174         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4175         Cvar_RegisterVariable(&r_hdr_glowintensity);
4176         Cvar_RegisterVariable(&r_hdr_range);
4177         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4178         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4179         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4180         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4181         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4182         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4183         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4184         Cvar_RegisterVariable(&developer_texturelogging);
4185         Cvar_RegisterVariable(&gl_lightmaps);
4186         Cvar_RegisterVariable(&r_test);
4187         Cvar_RegisterVariable(&r_glsl_saturation);
4188         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4189         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4190         Cvar_RegisterVariable(&r_framedatasize);
4191         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4192                 Cvar_SetValue("r_fullbrights", 0);
4193         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4194 }
4195
4196 extern void R_Textures_Init(void);
4197 extern void GL_Draw_Init(void);
4198 extern void GL_Main_Init(void);
4199 extern void R_Shadow_Init(void);
4200 extern void R_Sky_Init(void);
4201 extern void GL_Surf_Init(void);
4202 extern void R_Particles_Init(void);
4203 extern void R_Explosion_Init(void);
4204 extern void gl_backend_init(void);
4205 extern void Sbar_Init(void);
4206 extern void R_LightningBeams_Init(void);
4207 extern void Mod_RenderInit(void);
4208 extern void Font_Init(void);
4209
4210 void Render_Init(void)
4211 {
4212         gl_backend_init();
4213         R_Textures_Init();
4214         GL_Main_Init();
4215         Font_Init();
4216         GL_Draw_Init();
4217         R_Shadow_Init();
4218         R_Sky_Init();
4219         GL_Surf_Init();
4220         Sbar_Init();
4221         R_Particles_Init();
4222         R_Explosion_Init();
4223         R_LightningBeams_Init();
4224         Mod_RenderInit();
4225 }
4226
4227 /*
4228 ===============
4229 GL_Init
4230 ===============
4231 */
4232 extern char *ENGINE_EXTENSIONS;
4233 void GL_Init (void)
4234 {
4235         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4236         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4237         gl_version = (const char *)qglGetString(GL_VERSION);
4238         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4239
4240         if (!gl_extensions)
4241                 gl_extensions = "";
4242         if (!gl_platformextensions)
4243                 gl_platformextensions = "";
4244
4245         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4246         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4247         Con_Printf("GL_VERSION: %s\n", gl_version);
4248         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4249         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4250
4251         VID_CheckExtensions();
4252
4253         // LordHavoc: report supported extensions
4254         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4255
4256         // clear to black (loading plaque will be seen over this)
4257         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4258 }
4259
4260 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4261 {
4262         int i;
4263         mplane_t *p;
4264         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4265         {
4266                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4267                 if (i == 4)
4268                         continue;
4269                 p = r_refdef.view.frustum + i;
4270                 switch(p->signbits)
4271                 {
4272                 default:
4273                 case 0:
4274                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 1:
4278                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 2:
4282                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 case 3:
4286                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4287                                 return true;
4288                         break;
4289                 case 4:
4290                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 case 5:
4294                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4295                                 return true;
4296                         break;
4297                 case 6:
4298                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4299                                 return true;
4300                         break;
4301                 case 7:
4302                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4303                                 return true;
4304                         break;
4305                 }
4306         }
4307         return false;
4308 }
4309
4310 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4311 {
4312         int i;
4313         const mplane_t *p;
4314         for (i = 0;i < numplanes;i++)
4315         {
4316                 p = planes + i;
4317                 switch(p->signbits)
4318                 {
4319                 default:
4320                 case 0:
4321                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 1:
4325                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 2:
4329                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 case 3:
4333                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4334                                 return true;
4335                         break;
4336                 case 4:
4337                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4338                                 return true;
4339                         break;
4340                 case 5:
4341                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4342                                 return true;
4343                         break;
4344                 case 6:
4345                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4346                                 return true;
4347                         break;
4348                 case 7:
4349                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4350                                 return true;
4351                         break;
4352                 }
4353         }
4354         return false;
4355 }
4356
4357 //==================================================================================
4358
4359 // LordHavoc: this stores temporary data used within the same frame
4360
4361 typedef struct r_framedata_mem_s
4362 {
4363         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4364         size_t size; // how much usable space
4365         size_t current; // how much space in use
4366         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4367         size_t wantedsize; // how much space was allocated
4368         unsigned char *data; // start of real data (16byte aligned)
4369 }
4370 r_framedata_mem_t;
4371
4372 static r_framedata_mem_t *r_framedata_mem;
4373
4374 void R_FrameData_Reset(void)
4375 {
4376         while (r_framedata_mem)
4377         {
4378                 r_framedata_mem_t *next = r_framedata_mem->purge;
4379                 Mem_Free(r_framedata_mem);
4380                 r_framedata_mem = next;
4381         }
4382 }
4383
4384 void R_FrameData_Resize(void)
4385 {
4386         size_t wantedsize;
4387         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4388         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4389         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4390         {
4391                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4392                 newmem->wantedsize = wantedsize;
4393                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4394                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4395                 newmem->current = 0;
4396                 newmem->mark = 0;
4397                 newmem->purge = r_framedata_mem;
4398                 r_framedata_mem = newmem;
4399         }
4400 }
4401
4402 void R_FrameData_NewFrame(void)
4403 {
4404         R_FrameData_Resize();
4405         if (!r_framedata_mem)
4406                 return;
4407         // if we ran out of space on the last frame, free the old memory now
4408         while (r_framedata_mem->purge)
4409         {
4410                 // repeatedly remove the second item in the list, leaving only head
4411                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4412                 Mem_Free(r_framedata_mem->purge);
4413                 r_framedata_mem->purge = next;
4414         }
4415         // reset the current mem pointer
4416         r_framedata_mem->current = 0;
4417         r_framedata_mem->mark = 0;
4418 }
4419
4420 void *R_FrameData_Alloc(size_t size)
4421 {
4422         void *data;
4423
4424         // align to 16 byte boundary - the data pointer is already aligned, so we
4425         // only need to ensure the size of every allocation is also aligned
4426         size = (size + 15) & ~15;
4427
4428         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4429         {
4430                 // emergency - we ran out of space, allocate more memory
4431                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4432                 R_FrameData_Resize();
4433         }
4434
4435         data = r_framedata_mem->data + r_framedata_mem->current;
4436         r_framedata_mem->current += size;
4437
4438         // count the usage for stats
4439         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4440         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4441
4442         return (void *)data;
4443 }
4444
4445 void *R_FrameData_Store(size_t size, void *data)
4446 {
4447         void *d = R_FrameData_Alloc(size);
4448         if (d && data)
4449                 memcpy(d, data, size);
4450         return d;
4451 }
4452
4453 void R_FrameData_SetMark(void)
4454 {
4455         if (!r_framedata_mem)
4456                 return;
4457         r_framedata_mem->mark = r_framedata_mem->current;
4458 }
4459
4460 void R_FrameData_ReturnToMark(void)
4461 {
4462         if (!r_framedata_mem)
4463                 return;
4464         r_framedata_mem->current = r_framedata_mem->mark;
4465 }
4466
4467 //==================================================================================
4468
4469 // LordHavoc: animcache originally written by Echon, rewritten since then
4470
4471 /**
4472  * Animation cache prevents re-generating mesh data for an animated model
4473  * multiple times in one frame for lighting, shadowing, reflections, etc.
4474  */
4475
4476 void R_AnimCache_Free(void)
4477 {
4478 }
4479
4480 void R_AnimCache_ClearCache(void)
4481 {
4482         int i;
4483         entity_render_t *ent;
4484
4485         for (i = 0;i < r_refdef.scene.numentities;i++)
4486         {
4487                 ent = r_refdef.scene.entities[i];
4488                 ent->animcache_vertex3f = NULL;
4489                 ent->animcache_normal3f = NULL;
4490                 ent->animcache_svector3f = NULL;
4491                 ent->animcache_tvector3f = NULL;
4492                 ent->animcache_vertexmesh = NULL;
4493                 ent->animcache_vertex3fbuffer = NULL;
4494                 ent->animcache_vertexmeshbuffer = NULL;
4495         }
4496 }
4497
4498 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4499 {
4500         int i;
4501
4502         // check if we need the meshbuffers
4503         if (!vid.useinterleavedarrays)
4504                 return;
4505
4506         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4507                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4508         // TODO: upload vertex3f buffer?
4509         if (ent->animcache_vertexmesh)
4510         {
4511                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4512                 for (i = 0;i < numvertices;i++)
4513                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4514                 if (ent->animcache_svector3f)
4515                         for (i = 0;i < numvertices;i++)
4516                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4517                 if (ent->animcache_tvector3f)
4518                         for (i = 0;i < numvertices;i++)
4519                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4520                 if (ent->animcache_normal3f)
4521                         for (i = 0;i < numvertices;i++)
4522                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4523                 // TODO: upload vertexmeshbuffer?
4524         }
4525 }
4526
4527 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4528 {
4529         dp_model_t *model = ent->model;
4530         int numvertices;
4531         // see if it's already cached this frame
4532         if (ent->animcache_vertex3f)
4533         {
4534                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4535                 if (wantnormals || wanttangents)
4536                 {
4537                         if (ent->animcache_normal3f)
4538                                 wantnormals = false;
4539                         if (ent->animcache_svector3f)
4540                                 wanttangents = false;
4541                         if (wantnormals || wanttangents)
4542                         {
4543                                 numvertices = model->surfmesh.num_vertices;
4544                                 if (wantnormals)
4545                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546                                 if (wanttangents)
4547                                 {
4548                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550                                 }
4551                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4552                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4553                         }
4554                 }
4555         }
4556         else
4557         {
4558                 // see if this ent is worth caching
4559                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4560                         return false;
4561                 // get some memory for this entity and generate mesh data
4562                 numvertices = model->surfmesh.num_vertices;
4563                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 if (wantnormals)
4565                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566                 if (wanttangents)
4567                 {
4568                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4570                 }
4571                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4572                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4573         }
4574         return true;
4575 }
4576
4577 void R_AnimCache_CacheVisibleEntities(void)
4578 {
4579         int i;
4580         qboolean wantnormals = true;
4581         qboolean wanttangents = !r_showsurfaces.integer;
4582
4583         switch(vid.renderpath)
4584         {
4585         case RENDERPATH_GL20:
4586         case RENDERPATH_D3D9:
4587         case RENDERPATH_D3D10:
4588         case RENDERPATH_D3D11:
4589         case RENDERPATH_GLES2:
4590                 break;
4591         case RENDERPATH_GL11:
4592         case RENDERPATH_GL13:
4593         case RENDERPATH_GLES1:
4594                 wanttangents = false;
4595                 break;
4596         case RENDERPATH_SOFT:
4597                 break;
4598         }
4599
4600         if (r_shownormals.integer)
4601                 wanttangents = wantnormals = true;
4602
4603         // TODO: thread this
4604         // NOTE: R_PrepareRTLights() also caches entities
4605
4606         for (i = 0;i < r_refdef.scene.numentities;i++)
4607                 if (r_refdef.viewcache.entityvisible[i])
4608                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4609 }
4610
4611 //==================================================================================
4612
4613 extern cvar_t r_overheadsprites_pushback;
4614
4615 static void R_View_UpdateEntityLighting (void)
4616 {
4617         int i;
4618         entity_render_t *ent;
4619         vec3_t tempdiffusenormal, avg;
4620         vec_t f, fa, fd, fdd;
4621         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4622
4623         for (i = 0;i < r_refdef.scene.numentities;i++)
4624         {
4625                 ent = r_refdef.scene.entities[i];
4626
4627                 // skip unseen models
4628                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4629                         continue;
4630
4631                 // skip bsp models
4632                 if (ent->model && ent->model->brush.num_leafs)
4633                 {
4634                         // TODO: use modellight for r_ambient settings on world?
4635                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4636                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4637                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4638                         continue;
4639                 }
4640
4641                 // fetch the lighting from the worldmodel data
4642                 VectorClear(ent->modellight_ambient);
4643                 VectorClear(ent->modellight_diffuse);
4644                 VectorClear(tempdiffusenormal);
4645                 if (ent->flags & RENDER_LIGHT)
4646                 {
4647                         vec3_t org;
4648                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4649
4650                         // complete lightning for lit sprites
4651                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4652                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4653                         {
4654                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4655                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4656                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4657                         }
4658                         else
4659                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4660
4661                         if(ent->flags & RENDER_EQUALIZE)
4662                         {
4663                                 // first fix up ambient lighting...
4664                                 if(r_equalize_entities_minambient.value > 0)
4665                                 {
4666                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4667                                         if(fd > 0)
4668                                         {
4669                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4670                                                 if(fa < r_equalize_entities_minambient.value * fd)
4671                                                 {
4672                                                         // solve:
4673                                                         //   fa'/fd' = minambient
4674                                                         //   fa'+0.25*fd' = fa+0.25*fd
4675                                                         //   ...
4676                                                         //   fa' = fd' * minambient
4677                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4678                                                         //   ...
4679                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4680                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4681                                                         //   ...
4682                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4683                                                         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
4684                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4685                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4686                                                 }
4687                                         }
4688                                 }
4689
4690                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4691                                 {
4692                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4693                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4694                                         f = fa + 0.25 * fd;
4695                                         if(f > 0)
4696                                         {
4697                                                 // adjust brightness and saturation to target
4698                                                 avg[0] = avg[1] = avg[2] = fa / f;
4699                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4700                                                 avg[0] = avg[1] = avg[2] = fd / f;
4701                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4702                                         }
4703                                 }
4704                         }
4705                 }
4706                 else // highly rare
4707                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4708
4709                 // move the light direction into modelspace coordinates for lighting code
4710                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4711                 if(VectorLength2(ent->modellight_lightdir) == 0)
4712                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4713                 VectorNormalize(ent->modellight_lightdir);
4714         }
4715 }
4716
4717 #define MAX_LINEOFSIGHTTRACES 64
4718
4719 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4720 {
4721         int i;
4722         vec3_t boxmins, boxmaxs;
4723         vec3_t start;
4724         vec3_t end;
4725         dp_model_t *model = r_refdef.scene.worldmodel;
4726
4727         if (!model || !model->brush.TraceLineOfSight)
4728                 return true;
4729
4730         // expand the box a little
4731         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4732         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4733         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4734         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4735         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4736         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4737
4738         // return true if eye is inside enlarged box
4739         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4740                 return true;
4741
4742         // try center
4743         VectorCopy(eye, start);
4744         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4745         if (model->brush.TraceLineOfSight(model, start, end))
4746                 return true;
4747
4748         // try various random positions
4749         for (i = 0;i < numsamples;i++)
4750         {
4751                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4752                 if (model->brush.TraceLineOfSight(model, start, end))
4753                         return true;
4754         }
4755
4756         return false;
4757 }
4758
4759
4760 static void R_View_UpdateEntityVisible (void)
4761 {
4762         int i;
4763         int renderimask;
4764         int samples;
4765         entity_render_t *ent;
4766
4767         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4768                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4769                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4770                 :                                                          RENDER_EXTERIORMODEL;
4771         if (!r_drawviewmodel.integer)
4772                 renderimask |= RENDER_VIEWMODEL;
4773         if (!r_drawexteriormodel.integer)
4774                 renderimask |= RENDER_EXTERIORMODEL;
4775         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4776         {
4777                 // worldmodel can check visibility
4778                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4779                 for (i = 0;i < r_refdef.scene.numentities;i++)
4780                 {
4781                         ent = r_refdef.scene.entities[i];
4782                         if (!(ent->flags & renderimask))
4783                         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)))
4784                         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))
4785                                 r_refdef.viewcache.entityvisible[i] = true;
4786                 }
4787         }
4788         else
4789         {
4790                 // no worldmodel or it can't check visibility
4791                 for (i = 0;i < r_refdef.scene.numentities;i++)
4792                 {
4793                         ent = r_refdef.scene.entities[i];
4794                         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));
4795                 }
4796         }
4797         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4798                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4799         {
4800                 for (i = 0;i < r_refdef.scene.numentities;i++)
4801                 {
4802                         if (!r_refdef.viewcache.entityvisible[i])
4803                                 continue;
4804                         ent = r_refdef.scene.entities[i];
4805                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4806                         {
4807                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4808                                 if (samples < 0)
4809                                         continue; // temp entities do pvs only
4810                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4811                                         ent->last_trace_visibility = realtime;
4812                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4813                                         r_refdef.viewcache.entityvisible[i] = 0;
4814                         }
4815                 }
4816         }
4817 }
4818
4819 /// only used if skyrendermasked, and normally returns false
4820 int R_DrawBrushModelsSky (void)
4821 {
4822         int i, sky;
4823         entity_render_t *ent;
4824
4825         sky = false;
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                 if (!ent->model || !ent->model->DrawSky)
4832                         continue;
4833                 ent->model->DrawSky(ent);
4834                 sky = true;
4835         }
4836         return sky;
4837 }
4838
4839 static void R_DrawNoModel(entity_render_t *ent);
4840 static void R_DrawModels(void)
4841 {
4842         int i;
4843         entity_render_t *ent;
4844
4845         for (i = 0;i < r_refdef.scene.numentities;i++)
4846         {
4847                 if (!r_refdef.viewcache.entityvisible[i])
4848                         continue;
4849                 ent = r_refdef.scene.entities[i];
4850                 r_refdef.stats.entities++;
4851                 /*
4852                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4853                 {
4854                         vec3_t f, l, u, o;
4855                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4856                         Con_Printf("R_DrawModels\n");
4857                         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]);
4858                         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);
4859                         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);
4860                 }
4861                 */
4862                 if (ent->model && ent->model->Draw != NULL)
4863                         ent->model->Draw(ent);
4864                 else
4865                         R_DrawNoModel(ent);
4866         }
4867 }
4868
4869 static void R_DrawModelsDepth(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 if (!r_refdef.viewcache.entityvisible[i])
4877                         continue;
4878                 ent = r_refdef.scene.entities[i];
4879                 if (ent->model && ent->model->DrawDepth != NULL)
4880                         ent->model->DrawDepth(ent);
4881         }
4882 }
4883
4884 static void R_DrawModelsDebug(void)
4885 {
4886         int i;
4887         entity_render_t *ent;
4888
4889         for (i = 0;i < r_refdef.scene.numentities;i++)
4890         {
4891                 if (!r_refdef.viewcache.entityvisible[i])
4892                         continue;
4893                 ent = r_refdef.scene.entities[i];
4894                 if (ent->model && ent->model->DrawDebug != NULL)
4895                         ent->model->DrawDebug(ent);
4896         }
4897 }
4898
4899 static void R_DrawModelsAddWaterPlanes(void)
4900 {
4901         int i;
4902         entity_render_t *ent;
4903
4904         for (i = 0;i < r_refdef.scene.numentities;i++)
4905         {
4906                 if (!r_refdef.viewcache.entityvisible[i])
4907                         continue;
4908                 ent = r_refdef.scene.entities[i];
4909                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4910                         ent->model->DrawAddWaterPlanes(ent);
4911         }
4912 }
4913
4914 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4915 {
4916         if (r_hdr_irisadaptation.integer)
4917         {
4918                 vec3_t ambient;
4919                 vec3_t diffuse;
4920                 vec3_t diffusenormal;
4921                 vec_t brightness;
4922                 vec_t goal;
4923                 vec_t adjust;
4924                 vec_t current;
4925                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4926                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4927                 brightness = max(0.0000001f, brightness);
4928                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4929                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4930                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4931                 current = r_hdr_irisadaptation_value.value;
4932                 if (current < goal)
4933                         current = min(current + adjust, goal);
4934                 else if (current > goal)
4935                         current = max(current - adjust, goal);
4936                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4937                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4938         }
4939         else if (r_hdr_irisadaptation_value.value != 1.0f)
4940                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4941 }
4942
4943 static void R_View_SetFrustum(const int *scissor)
4944 {
4945         int i;
4946         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4947         vec3_t forward, left, up, origin, v;
4948
4949         if(scissor)
4950         {
4951                 // flipped x coordinates (because x points left here)
4952                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4953                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4954
4955                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4956                 switch(vid.renderpath)
4957                 {
4958                         case RENDERPATH_D3D9:
4959                         case RENDERPATH_D3D10:
4960                         case RENDERPATH_D3D11:
4961                                 // non-flipped y coordinates
4962                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4963                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4964                                 break;
4965                         case RENDERPATH_SOFT:
4966                         case RENDERPATH_GL11:
4967                         case RENDERPATH_GL13:
4968                         case RENDERPATH_GL20:
4969                         case RENDERPATH_GLES1:
4970                         case RENDERPATH_GLES2:
4971                                 // non-flipped y coordinates
4972                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4973                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4974                                 break;
4975                 }
4976         }
4977
4978         // we can't trust r_refdef.view.forward and friends in reflected scenes
4979         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4980
4981 #if 0
4982         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4983         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4984         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4985         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4986         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4987         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4988         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4989         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4990         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4991         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4992         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4993         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4994 #endif
4995
4996 #if 0
4997         zNear = r_refdef.nearclip;
4998         nudge = 1.0 - 1.0 / (1<<23);
4999         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5000         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5001         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5002         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5003         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5004         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5005         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5006         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5007 #endif
5008
5009
5010
5011 #if 0
5012         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5013         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5014         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5015         r_refdef.view.frustum[0].dist = m[15] - m[12];
5016
5017         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5018         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5019         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5020         r_refdef.view.frustum[1].dist = m[15] + m[12];
5021
5022         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5023         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5024         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5025         r_refdef.view.frustum[2].dist = m[15] - m[13];
5026
5027         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5028         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5029         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5030         r_refdef.view.frustum[3].dist = m[15] + m[13];
5031
5032         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5033         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5034         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5035         r_refdef.view.frustum[4].dist = m[15] - m[14];
5036
5037         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5038         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5039         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5040         r_refdef.view.frustum[5].dist = m[15] + m[14];
5041 #endif
5042
5043         if (r_refdef.view.useperspective)
5044         {
5045                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5046                 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]);
5047                 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]);
5048                 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]);
5049                 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]);
5050
5051                 // then the normals from the corners relative to origin
5052                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5053                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5054                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5055                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5056
5057                 // in a NORMAL view, forward cross left == up
5058                 // in a REFLECTED view, forward cross left == down
5059                 // so our cross products above need to be adjusted for a left handed coordinate system
5060                 CrossProduct(forward, left, v);
5061                 if(DotProduct(v, up) < 0)
5062                 {
5063                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5064                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5065                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5066                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5067                 }
5068
5069                 // Leaving those out was a mistake, those were in the old code, and they
5070                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5071                 // I couldn't reproduce it after adding those normalizations. --blub
5072                 VectorNormalize(r_refdef.view.frustum[0].normal);
5073                 VectorNormalize(r_refdef.view.frustum[1].normal);
5074                 VectorNormalize(r_refdef.view.frustum[2].normal);
5075                 VectorNormalize(r_refdef.view.frustum[3].normal);
5076
5077                 // make the corners absolute
5078                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5079                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5080                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5081                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5082
5083                 // one more normal
5084                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5085
5086                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5087                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5088                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5089                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5090                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5091         }
5092         else
5093         {
5094                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5095                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5096                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5097                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5098                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5099                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5100                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5101                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5102                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5103                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5104         }
5105         r_refdef.view.numfrustumplanes = 5;
5106
5107         if (r_refdef.view.useclipplane)
5108         {
5109                 r_refdef.view.numfrustumplanes = 6;
5110                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5111         }
5112
5113         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5114                 PlaneClassify(r_refdef.view.frustum + i);
5115
5116         // LordHavoc: note to all quake engine coders, Quake had a special case
5117         // for 90 degrees which assumed a square view (wrong), so I removed it,
5118         // Quake2 has it disabled as well.
5119
5120         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5121         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5122         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5123         //PlaneClassify(&frustum[0]);
5124
5125         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5126         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5127         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5128         //PlaneClassify(&frustum[1]);
5129
5130         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5131         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5132         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5133         //PlaneClassify(&frustum[2]);
5134
5135         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5136         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5137         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5138         //PlaneClassify(&frustum[3]);
5139
5140         // nearclip plane
5141         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5142         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5143         //PlaneClassify(&frustum[4]);
5144 }
5145
5146 void R_View_UpdateWithScissor(const int *myscissor)
5147 {
5148         R_Main_ResizeViewCache();
5149         R_View_SetFrustum(myscissor);
5150         R_View_WorldVisibility(r_refdef.view.useclipplane);
5151         R_View_UpdateEntityVisible();
5152         R_View_UpdateEntityLighting();
5153 }
5154
5155 void R_View_Update(void)
5156 {
5157         R_Main_ResizeViewCache();
5158         R_View_SetFrustum(NULL);
5159         R_View_WorldVisibility(r_refdef.view.useclipplane);
5160         R_View_UpdateEntityVisible();
5161         R_View_UpdateEntityLighting();
5162 }
5163
5164 float viewscalefpsadjusted = 1.0f;
5165
5166 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5167 {
5168         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5169         scale = bound(0.03125f, scale, 1.0f);
5170         *outwidth = (int)ceil(width * scale);
5171         *outheight = (int)ceil(height * scale);
5172 }
5173
5174 void R_Mesh_SetMainRenderTargets(void)
5175 {
5176         if (r_bloomstate.fbo_framebuffer)
5177                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5178         else
5179                 R_Mesh_ResetRenderTargets();
5180 }
5181
5182 void R_SetupView(qboolean allowwaterclippingplane)
5183 {
5184         const float *customclipplane = NULL;
5185         float plane[4];
5186         int scaledwidth, scaledheight;
5187         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5188         {
5189                 // LordHavoc: couldn't figure out how to make this approach the
5190                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5191                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5192                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5193                         dist = r_refdef.view.clipplane.dist;
5194                 plane[0] = r_refdef.view.clipplane.normal[0];
5195                 plane[1] = r_refdef.view.clipplane.normal[1];
5196                 plane[2] = r_refdef.view.clipplane.normal[2];
5197                 plane[3] = -dist;
5198                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5199         }
5200
5201         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5202         if (!r_refdef.view.useperspective)
5203                 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);
5204         else if (vid.stencil && r_useinfinitefarclip.integer)
5205                 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);
5206         else
5207                 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);
5208         R_Mesh_SetMainRenderTargets();
5209         R_SetViewport(&r_refdef.view.viewport);
5210         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5211         {
5212                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5213                 float screenplane[4];
5214                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5215                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5216                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5217                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5218                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5219         }
5220 }
5221
5222 void R_EntityMatrix(const matrix4x4_t *matrix)
5223 {
5224         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5225         {
5226                 gl_modelmatrixchanged = false;
5227                 gl_modelmatrix = *matrix;
5228                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5229                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5230                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5231                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5232                 CHECKGLERROR
5233                 switch(vid.renderpath)
5234                 {
5235                 case RENDERPATH_D3D9:
5236 #ifdef SUPPORTD3D
5237                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5238                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5239 #endif
5240                         break;
5241                 case RENDERPATH_D3D10:
5242                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5243                         break;
5244                 case RENDERPATH_D3D11:
5245                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5246                         break;
5247                 case RENDERPATH_GL11:
5248                 case RENDERPATH_GL13:
5249                 case RENDERPATH_GLES1:
5250                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5251                         break;
5252                 case RENDERPATH_SOFT:
5253                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5254                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5255                         break;
5256                 case RENDERPATH_GL20:
5257                 case RENDERPATH_GLES2:
5258                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5259                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5260                         break;
5261                 }
5262         }
5263 }
5264
5265 void R_ResetViewRendering2D(void)
5266 {
5267         r_viewport_t viewport;
5268         DrawQ_Finish();
5269
5270         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5271         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);
5272         R_Mesh_ResetRenderTargets();
5273         R_SetViewport(&viewport);
5274         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5275         GL_Color(1, 1, 1, 1);
5276         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5277         GL_BlendFunc(GL_ONE, GL_ZERO);
5278         GL_ScissorTest(false);
5279         GL_DepthMask(false);
5280         GL_DepthRange(0, 1);
5281         GL_DepthTest(false);
5282         GL_DepthFunc(GL_LEQUAL);
5283         R_EntityMatrix(&identitymatrix);
5284         R_Mesh_ResetTextureState();
5285         GL_PolygonOffset(0, 0);
5286         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5287         switch(vid.renderpath)
5288         {
5289         case RENDERPATH_GL11:
5290         case RENDERPATH_GL13:
5291         case RENDERPATH_GL20:
5292         case RENDERPATH_GLES1:
5293         case RENDERPATH_GLES2:
5294                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5295                 break;
5296         case RENDERPATH_D3D9:
5297         case RENDERPATH_D3D10:
5298         case RENDERPATH_D3D11:
5299         case RENDERPATH_SOFT:
5300                 break;
5301         }
5302         GL_CullFace(GL_NONE);
5303 }
5304
5305 void R_ResetViewRendering3D(void)
5306 {
5307         DrawQ_Finish();
5308
5309         R_SetupView(true);
5310         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5311         GL_Color(1, 1, 1, 1);
5312         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5313         GL_BlendFunc(GL_ONE, GL_ZERO);
5314         GL_ScissorTest(true);
5315         GL_DepthMask(true);
5316         GL_DepthRange(0, 1);
5317         GL_DepthTest(true);
5318         GL_DepthFunc(GL_LEQUAL);
5319         R_EntityMatrix(&identitymatrix);
5320         R_Mesh_ResetTextureState();
5321         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5322         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5323         switch(vid.renderpath)
5324         {
5325         case RENDERPATH_GL11:
5326         case RENDERPATH_GL13:
5327         case RENDERPATH_GL20:
5328         case RENDERPATH_GLES1:
5329         case RENDERPATH_GLES2:
5330                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5331                 break;
5332         case RENDERPATH_D3D9:
5333         case RENDERPATH_D3D10:
5334         case RENDERPATH_D3D11:
5335         case RENDERPATH_SOFT:
5336                 break;
5337         }
5338         GL_CullFace(r_refdef.view.cullface_back);
5339 }
5340
5341 /*
5342 ================
5343 R_RenderView_UpdateViewVectors
5344 ================
5345 */
5346 static void R_RenderView_UpdateViewVectors(void)
5347 {
5348         // break apart the view matrix into vectors for various purposes
5349         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5350         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5351         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5352         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5353         // make an inverted copy of the view matrix for tracking sprites
5354         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5355 }
5356
5357 void R_RenderScene(void);
5358 void R_RenderWaterPlanes(void);
5359
5360 static void R_Water_StartFrame(void)
5361 {
5362         int i;
5363         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5364         r_waterstate_waterplane_t *p;
5365
5366         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5367                 return;
5368
5369         switch(vid.renderpath)
5370         {
5371         case RENDERPATH_GL20:
5372         case RENDERPATH_D3D9:
5373         case RENDERPATH_D3D10:
5374         case RENDERPATH_D3D11:
5375         case RENDERPATH_SOFT:
5376         case RENDERPATH_GLES2:
5377                 break;
5378         case RENDERPATH_GL11:
5379         case RENDERPATH_GL13:
5380         case RENDERPATH_GLES1:
5381                 return;
5382         }
5383
5384         // set waterwidth and waterheight to the water resolution that will be
5385         // used (often less than the screen resolution for faster rendering)
5386         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5387
5388         // calculate desired texture sizes
5389         // can't use water if the card does not support the texture size
5390         if (!r_water.integer || r_showsurfaces.integer)
5391                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5392         else if (vid.support.arb_texture_non_power_of_two)
5393         {
5394                 texturewidth = waterwidth;
5395                 textureheight = waterheight;
5396                 camerawidth = waterwidth;
5397                 cameraheight = waterheight;
5398         }
5399         else
5400         {
5401                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5402                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5403                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5404                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5405         }
5406
5407         // allocate textures as needed
5408         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5409         {
5410                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5411                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5412                 {
5413                         if (p->texture_refraction)
5414                                 R_FreeTexture(p->texture_refraction);
5415                         p->texture_refraction = NULL;
5416                         if (p->texture_reflection)
5417                                 R_FreeTexture(p->texture_reflection);
5418                         p->texture_reflection = NULL;
5419                         if (p->texture_camera)
5420                                 R_FreeTexture(p->texture_camera);
5421                         p->texture_camera = NULL;
5422                 }
5423                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5424                 r_waterstate.texturewidth = texturewidth;
5425                 r_waterstate.textureheight = textureheight;
5426                 r_waterstate.camerawidth = camerawidth;
5427                 r_waterstate.cameraheight = cameraheight;
5428         }
5429
5430         if (r_waterstate.texturewidth)
5431         {
5432                 int scaledwidth, scaledheight;
5433
5434                 r_waterstate.enabled = true;
5435
5436                 // when doing a reduced render (HDR) we want to use a smaller area
5437                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5438                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5439                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5440
5441                 // set up variables that will be used in shader setup
5442                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5443                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5444                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5445                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5446         }
5447
5448         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5449         r_waterstate.numwaterplanes = 0;
5450 }
5451
5452 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5453 {
5454         int triangleindex, planeindex;
5455         const int *e;
5456         vec3_t vert[3];
5457         vec3_t normal;
5458         vec3_t center;
5459         mplane_t plane;
5460         r_waterstate_waterplane_t *p;
5461         texture_t *t = R_GetCurrentTexture(surface->texture);
5462
5463         // just use the first triangle with a valid normal for any decisions
5464         VectorClear(normal);
5465         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5466         {
5467                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5468                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5469                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5470                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5471                 if (VectorLength2(normal) >= 0.001)
5472                         break;
5473         }
5474
5475         VectorCopy(normal, plane.normal);
5476         VectorNormalize(plane.normal);
5477         plane.dist = DotProduct(vert[0], plane.normal);
5478         PlaneClassify(&plane);
5479         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5480         {
5481                 // skip backfaces (except if nocullface is set)
5482                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5483                         return;
5484                 VectorNegate(plane.normal, plane.normal);
5485                 plane.dist *= -1;
5486                 PlaneClassify(&plane);
5487         }
5488
5489
5490         // find a matching plane if there is one
5491         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5492                 if(p->camera_entity == t->camera_entity)
5493                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5494                                 break;
5495         if (planeindex >= r_waterstate.maxwaterplanes)
5496                 return; // nothing we can do, out of planes
5497
5498         // if this triangle does not fit any known plane rendered this frame, add one
5499         if (planeindex >= r_waterstate.numwaterplanes)
5500         {
5501                 // store the new plane
5502                 r_waterstate.numwaterplanes++;
5503                 p->plane = plane;
5504                 // clear materialflags and pvs
5505                 p->materialflags = 0;
5506                 p->pvsvalid = false;
5507                 p->camera_entity = t->camera_entity;
5508                 VectorCopy(surface->mins, p->mins);
5509                 VectorCopy(surface->maxs, p->maxs);
5510         }
5511         else
5512         {
5513                 // merge mins/maxs
5514                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5515                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5516                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5517                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5518                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5519                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5520         }
5521         // merge this surface's materialflags into the waterplane
5522         p->materialflags |= t->currentmaterialflags;
5523         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5524         {
5525                 // merge this surface's PVS into the waterplane
5526                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5527                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5528                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5529                 {
5530                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5531                         p->pvsvalid = true;
5532                 }
5533         }
5534 }
5535
5536 extern cvar_t r_drawparticles;
5537 extern cvar_t r_drawdecals;
5538
5539 static void R_Water_ProcessPlanes(void)
5540 {
5541         int myscissor[4];
5542         r_refdef_view_t originalview;
5543         r_refdef_view_t myview;
5544         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5545         r_waterstate_waterplane_t *p;
5546         vec3_t visorigin;
5547
5548         originalview = r_refdef.view;
5549
5550         // lowquality hack, temporarily shut down some cvars and restore afterwards
5551         qualityreduction = r_water_lowquality.integer;
5552         if (qualityreduction > 0)
5553         {
5554                 if (qualityreduction >= 1)
5555                 {
5556                         old_r_shadows = r_shadows.integer;
5557                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5558                         old_r_dlight = r_shadow_realtime_dlight.integer;
5559                         Cvar_SetValueQuick(&r_shadows, 0);
5560                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5561                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5562                 }
5563                 if (qualityreduction >= 2)
5564                 {
5565                         old_r_dynamic = r_dynamic.integer;
5566                         old_r_particles = r_drawparticles.integer;
5567                         old_r_decals = r_drawdecals.integer;
5568                         Cvar_SetValueQuick(&r_dynamic, 0);
5569                         Cvar_SetValueQuick(&r_drawparticles, 0);
5570                         Cvar_SetValueQuick(&r_drawdecals, 0);
5571                 }
5572         }
5573
5574         // make sure enough textures are allocated
5575         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5576         {
5577                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5578                 {
5579                         if (!p->texture_refraction)
5580                                 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);
5581                         if (!p->texture_refraction)
5582                                 goto error;
5583                 }
5584                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5585                 {
5586                         if (!p->texture_camera)
5587                                 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);
5588                         if (!p->texture_camera)
5589                                 goto error;
5590                 }
5591
5592                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5593                 {
5594                         if (!p->texture_reflection)
5595                                 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);
5596                         if (!p->texture_reflection)
5597                                 goto error;
5598                 }
5599         }
5600
5601         // render views
5602         r_refdef.view = originalview;
5603         r_refdef.view.showdebug = false;
5604         r_refdef.view.width = r_waterstate.waterwidth;
5605         r_refdef.view.height = r_waterstate.waterheight;
5606         r_refdef.view.useclipplane = true;
5607         myview = r_refdef.view;
5608         r_waterstate.renderingscene = true;
5609         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5610         {
5611                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5612                 {
5613                         r_refdef.view = myview;
5614                         if(r_water_scissormode.integer)
5615                         {
5616                                 R_SetupView(true);
5617                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5618                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5619                         }
5620
5621                         // render reflected scene and copy into texture
5622                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5623                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5624                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5625                         r_refdef.view.clipplane = p->plane;
5626                         // reverse the cullface settings for this render
5627                         r_refdef.view.cullface_front = GL_FRONT;
5628                         r_refdef.view.cullface_back = GL_BACK;
5629                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5630                         {
5631                                 r_refdef.view.usecustompvs = true;
5632                                 if (p->pvsvalid)
5633                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5634                                 else
5635                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5636                         }
5637
5638                         R_ResetViewRendering3D();
5639                         R_ClearScreen(r_refdef.fogenabled);
5640                         if(r_water_scissormode.integer & 2)
5641                                 R_View_UpdateWithScissor(myscissor);
5642                         else
5643                                 R_View_Update();
5644                         if(r_water_scissormode.integer & 1)
5645                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5646                         R_RenderScene();
5647
5648                         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);
5649                 }
5650
5651                 // render the normal view scene and copy into texture
5652                 // (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)
5653                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5654                 {
5655                         r_refdef.view = myview;
5656                         if(r_water_scissormode.integer)
5657                         {
5658                                 R_SetupView(true);
5659                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5660                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5661                         }
5662
5663                         r_waterstate.renderingrefraction = true;
5664
5665                         r_refdef.view.clipplane = p->plane;
5666                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5667                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5668
5669                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5670                         {
5671                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5672                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5673                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5674                                 R_RenderView_UpdateViewVectors();
5675                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5676                                 {
5677                                         r_refdef.view.usecustompvs = true;
5678                                         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);
5679                                 }
5680                         }
5681
5682                         PlaneClassify(&r_refdef.view.clipplane);
5683
5684                         R_ResetViewRendering3D();
5685                         R_ClearScreen(r_refdef.fogenabled);
5686                         if(r_water_scissormode.integer & 2)
5687                                 R_View_UpdateWithScissor(myscissor);
5688                         else
5689                                 R_View_Update();
5690                         if(r_water_scissormode.integer & 1)
5691                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5692                         R_RenderScene();
5693
5694                         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);
5695                         r_waterstate.renderingrefraction = false;
5696                 }
5697                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5698                 {
5699                         r_refdef.view = myview;
5700
5701                         r_refdef.view.clipplane = p->plane;
5702                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5703                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5704
5705                         r_refdef.view.width = r_waterstate.camerawidth;
5706                         r_refdef.view.height = r_waterstate.cameraheight;
5707                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5708                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5709
5710                         if(p->camera_entity)
5711                         {
5712                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5713                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5714                         }
5715
5716                         // note: all of the view is used for displaying... so
5717                         // there is no use in scissoring
5718
5719                         // reverse the cullface settings for this render
5720                         r_refdef.view.cullface_front = GL_FRONT;
5721                         r_refdef.view.cullface_back = GL_BACK;
5722                         // also reverse the view matrix
5723                         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
5724                         R_RenderView_UpdateViewVectors();
5725                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5726                         {
5727                                 r_refdef.view.usecustompvs = true;
5728                                 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);
5729                         }
5730                         
5731                         // camera needs no clipplane
5732                         r_refdef.view.useclipplane = false;
5733
5734                         PlaneClassify(&r_refdef.view.clipplane);
5735
5736                         R_ResetViewRendering3D();
5737                         R_ClearScreen(r_refdef.fogenabled);
5738                         R_View_Update();
5739                         R_RenderScene();
5740
5741                         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);
5742                         r_waterstate.renderingrefraction = false;
5743                 }
5744
5745         }
5746         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5747         r_waterstate.renderingscene = false;
5748         r_refdef.view = originalview;
5749         R_ResetViewRendering3D();
5750         R_ClearScreen(r_refdef.fogenabled);
5751         R_View_Update();
5752         goto finish;
5753 error:
5754         r_refdef.view = originalview;
5755         r_waterstate.renderingscene = false;
5756         Cvar_SetValueQuick(&r_water, 0);
5757         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5758 finish:
5759         // lowquality hack, restore cvars
5760         if (qualityreduction > 0)
5761         {
5762                 if (qualityreduction >= 1)
5763                 {
5764                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5765                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5766                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5767                 }
5768                 if (qualityreduction >= 2)
5769                 {
5770                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5771                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5772                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5773                 }
5774         }
5775 }
5776
5777 void R_Bloom_StartFrame(void)
5778 {
5779         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5780         int viewwidth, viewheight;
5781         textype_t textype;
5782
5783         if (r_viewscale_fpsscaling.integer)
5784         {
5785                 double actualframetime;
5786                 double targetframetime;
5787                 double adjust;
5788                 actualframetime = r_refdef.lastdrawscreentime;
5789                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5790                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5791                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5792                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5793                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5794                 viewscalefpsadjusted += adjust;
5795                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5796         }
5797         else
5798                 viewscalefpsadjusted = 1.0f;
5799
5800         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5801
5802         switch(vid.renderpath)
5803         {
5804         case RENDERPATH_GL20:
5805         case RENDERPATH_D3D9:
5806         case RENDERPATH_D3D10:
5807         case RENDERPATH_D3D11:
5808         case RENDERPATH_SOFT:
5809         case RENDERPATH_GLES2:
5810                 break;
5811         case RENDERPATH_GL11:
5812         case RENDERPATH_GL13:
5813         case RENDERPATH_GLES1:
5814                 return;
5815         }
5816
5817         // set bloomwidth and bloomheight to the bloom resolution that will be
5818         // used (often less than the screen resolution for faster rendering)
5819         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5820         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5821         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5822         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5823         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5824
5825         // calculate desired texture sizes
5826         if (vid.support.arb_texture_non_power_of_two)
5827         {
5828                 screentexturewidth = vid.width;
5829                 screentextureheight = vid.height;
5830                 bloomtexturewidth = r_bloomstate.bloomwidth;
5831                 bloomtextureheight = r_bloomstate.bloomheight;
5832         }
5833         else
5834         {
5835                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5836                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5837                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5838                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5839         }
5840
5841         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))
5842         {
5843                 Cvar_SetValueQuick(&r_hdr, 0);
5844                 Cvar_SetValueQuick(&r_bloom, 0);
5845                 Cvar_SetValueQuick(&r_motionblur, 0);
5846                 Cvar_SetValueQuick(&r_damageblur, 0);
5847         }
5848
5849         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)
5850                 screentexturewidth = screentextureheight = 0;
5851         if (!r_hdr.integer && !r_bloom.integer)
5852                 bloomtexturewidth = bloomtextureheight = 0;
5853
5854         textype = TEXTYPE_COLORBUFFER;
5855         switch (vid.renderpath)
5856         {
5857         case RENDERPATH_GL20:
5858         case RENDERPATH_GLES2:
5859                 if (vid.support.ext_framebuffer_object)
5860                 {
5861                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5862                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5863                 }
5864                 break;
5865         case RENDERPATH_GL11:
5866         case RENDERPATH_GL13:
5867         case RENDERPATH_GLES1:
5868         case RENDERPATH_D3D9:
5869         case RENDERPATH_D3D10:
5870         case RENDERPATH_D3D11:
5871         case RENDERPATH_SOFT:
5872                 break;
5873         }
5874
5875         // allocate textures as needed
5876         if (r_bloomstate.screentexturewidth != screentexturewidth
5877          || r_bloomstate.screentextureheight != screentextureheight
5878          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5879          || r_bloomstate.bloomtextureheight != bloomtextureheight
5880          || r_bloomstate.texturetype != textype
5881          || r_bloomstate.viewfbo != r_viewfbo.integer)
5882         {
5883                 if (r_bloomstate.texture_bloom)
5884                         R_FreeTexture(r_bloomstate.texture_bloom);
5885                 r_bloomstate.texture_bloom = NULL;
5886                 if (r_bloomstate.texture_screen)
5887                         R_FreeTexture(r_bloomstate.texture_screen);
5888                 r_bloomstate.texture_screen = NULL;
5889                 if (r_bloomstate.fbo_framebuffer)
5890                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5891                 r_bloomstate.fbo_framebuffer = 0;
5892                 if (r_bloomstate.texture_framebuffercolor)
5893                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5894                 r_bloomstate.texture_framebuffercolor = NULL;
5895                 if (r_bloomstate.texture_framebufferdepth)
5896                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5897                 r_bloomstate.texture_framebufferdepth = NULL;
5898                 r_bloomstate.screentexturewidth = screentexturewidth;
5899                 r_bloomstate.screentextureheight = screentextureheight;
5900                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5901                         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);
5902                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5903                 {
5904                         // FIXME: choose depth bits based on a cvar
5905                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5906                         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);
5907                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5908                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5909                         // render depth into one texture and normalmap into the other
5910                         if (qglDrawBuffer)
5911                         {
5912                                 int status;
5913                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5914                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5915                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5916                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5917                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5918                         }
5919                 }
5920                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5921                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5922                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5923                         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);
5924                 r_bloomstate.viewfbo = r_viewfbo.integer;
5925                 r_bloomstate.texturetype = textype;
5926         }
5927
5928         // when doing a reduced render (HDR) we want to use a smaller area
5929         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5930         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5931         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5932         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5933         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5934
5935         // set up a texcoord array for the full resolution screen image
5936         // (we have to keep this around to copy back during final render)
5937         r_bloomstate.screentexcoord2f[0] = 0;
5938         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5939         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5940         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5941         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5942         r_bloomstate.screentexcoord2f[5] = 0;
5943         r_bloomstate.screentexcoord2f[6] = 0;
5944         r_bloomstate.screentexcoord2f[7] = 0;
5945
5946         // set up a texcoord array for the reduced resolution bloom image
5947         // (which will be additive blended over the screen image)
5948         r_bloomstate.bloomtexcoord2f[0] = 0;
5949         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5950         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5951         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5952         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5953         r_bloomstate.bloomtexcoord2f[5] = 0;
5954         r_bloomstate.bloomtexcoord2f[6] = 0;
5955         r_bloomstate.bloomtexcoord2f[7] = 0;
5956
5957         switch(vid.renderpath)
5958         {
5959         case RENDERPATH_GL11:
5960         case RENDERPATH_GL13:
5961         case RENDERPATH_GL20:
5962         case RENDERPATH_SOFT:
5963         case RENDERPATH_GLES1:
5964         case RENDERPATH_GLES2:
5965                 break;
5966         case RENDERPATH_D3D9:
5967         case RENDERPATH_D3D10:
5968         case RENDERPATH_D3D11:
5969                 {
5970                         int i;
5971                         for (i = 0;i < 4;i++)
5972                         {
5973                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5974                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5975                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5976                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5977                         }
5978                 }
5979                 break;
5980         }
5981
5982         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5983         {
5984                 r_bloomstate.enabled = true;
5985                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5986         }
5987
5988         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);
5989
5990         if (r_bloomstate.fbo_framebuffer)
5991                 r_refdef.view.clear = true;
5992 }
5993
5994 void R_Bloom_CopyBloomTexture(float colorscale)
5995 {
5996         r_refdef.stats.bloom++;
5997
5998         // scale down screen texture to the bloom texture size
5999         CHECKGLERROR
6000         R_Mesh_SetMainRenderTargets();
6001         R_SetViewport(&r_bloomstate.viewport);
6002         GL_BlendFunc(GL_ONE, GL_ZERO);
6003         GL_Color(colorscale, colorscale, colorscale, 1);
6004         // 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...
6005         switch(vid.renderpath)
6006         {
6007         case RENDERPATH_GL11:
6008         case RENDERPATH_GL13:
6009         case RENDERPATH_GL20:
6010         case RENDERPATH_GLES1:
6011         case RENDERPATH_GLES2:
6012         case RENDERPATH_SOFT:
6013                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6014                 break;
6015         case RENDERPATH_D3D9:
6016         case RENDERPATH_D3D10:
6017         case RENDERPATH_D3D11:
6018                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6019                 break;
6020         }
6021         // TODO: do boxfilter scale-down in shader?
6022         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6023         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6024         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6025
6026         // we now have a bloom image in the framebuffer
6027         // copy it into the bloom image texture for later processing
6028         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);
6029         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6030 }
6031
6032 void R_Bloom_CopyHDRTexture(void)
6033 {
6034         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);
6035         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6036 }
6037
6038 void R_Bloom_MakeTexture(void)
6039 {
6040         int x, range, dir;
6041         float xoffset, yoffset, r, brighten;
6042
6043         r_refdef.stats.bloom++;
6044
6045         R_ResetViewRendering2D();
6046
6047         // we have a bloom image in the framebuffer
6048         CHECKGLERROR
6049         R_SetViewport(&r_bloomstate.viewport);
6050
6051         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6052         {
6053                 x *= 2;
6054                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6055                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6056                 GL_Color(r,r,r,1);
6057                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6058                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6059                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6061
6062                 // copy the vertically blurred bloom view to a texture
6063                 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);
6064                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6065         }
6066
6067         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6068         brighten = r_bloom_brighten.value;
6069         if (r_bloomstate.hdr)
6070                 brighten *= r_hdr_range.value;
6071         brighten = sqrt(brighten);
6072         if(range >= 1)
6073                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6074         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6075
6076         for (dir = 0;dir < 2;dir++)
6077         {
6078                 // blend on at multiple vertical offsets to achieve a vertical blur
6079                 // TODO: do offset blends using GLSL
6080                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6081                 GL_BlendFunc(GL_ONE, GL_ZERO);
6082                 for (x = -range;x <= range;x++)
6083                 {
6084                         if (!dir){xoffset = 0;yoffset = x;}
6085                         else {xoffset = x;yoffset = 0;}
6086                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6087                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6088                         // compute a texcoord array with the specified x and y offset
6089                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6090                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6091                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6092                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6093                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6094                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6095                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6096                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6097                         // this r value looks like a 'dot' particle, fading sharply to
6098                         // black at the edges
6099                         // (probably not realistic but looks good enough)
6100                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6101                         //r = brighten/(range*2+1);
6102                         r = brighten / (range * 2 + 1);
6103                         if(range >= 1)
6104                                 r *= (1 - x*x/(float)(range*range));
6105                         GL_Color(r, r, r, 1);
6106                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6107                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6108                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6109                         GL_BlendFunc(GL_ONE, GL_ONE);
6110                 }
6111
6112                 // copy the vertically blurred bloom view to a texture
6113                 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);
6114                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6115         }
6116 }
6117
6118 void R_HDR_RenderBloomTexture(void)
6119 {
6120         int oldwidth, oldheight;
6121         float oldcolorscale;
6122         qboolean oldwaterstate;
6123
6124         oldwaterstate = r_waterstate.enabled;
6125         oldcolorscale = r_refdef.view.colorscale;
6126         oldwidth = r_refdef.view.width;
6127         oldheight = r_refdef.view.height;
6128         r_refdef.view.width = r_bloomstate.bloomwidth;
6129         r_refdef.view.height = r_bloomstate.bloomheight;
6130
6131         if(r_hdr.integer < 2)
6132                 r_waterstate.enabled = false;
6133
6134         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6135         // TODO: add exposure compensation features
6136         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6137
6138         r_refdef.view.showdebug = false;
6139         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6140
6141         R_ResetViewRendering3D();
6142
6143         R_ClearScreen(r_refdef.fogenabled);
6144         if (r_timereport_active)
6145                 R_TimeReport("HDRclear");
6146
6147         R_View_Update();
6148         if (r_timereport_active)
6149                 R_TimeReport("visibility");
6150
6151         // only do secondary renders with HDR if r_hdr is 2 or higher
6152         r_waterstate.numwaterplanes = 0;
6153         if (r_waterstate.enabled)
6154                 R_RenderWaterPlanes();
6155
6156         r_refdef.view.showdebug = true;
6157         R_RenderScene();
6158         r_waterstate.numwaterplanes = 0;
6159
6160         R_ResetViewRendering2D();
6161
6162         R_Bloom_CopyHDRTexture();
6163         R_Bloom_MakeTexture();
6164
6165         // restore the view settings
6166         r_waterstate.enabled = oldwaterstate;
6167         r_refdef.view.width = oldwidth;
6168         r_refdef.view.height = oldheight;
6169         r_refdef.view.colorscale = oldcolorscale;
6170
6171         R_ResetViewRendering3D();
6172
6173         R_ClearScreen(r_refdef.fogenabled);
6174         if (r_timereport_active)
6175                 R_TimeReport("viewclear");
6176 }
6177
6178 static void R_BlendView(void)
6179 {
6180         unsigned int permutation;
6181         float uservecs[4][4];
6182
6183         switch (vid.renderpath)
6184         {
6185         case RENDERPATH_GL20:
6186         case RENDERPATH_D3D9:
6187         case RENDERPATH_D3D10:
6188         case RENDERPATH_D3D11:
6189         case RENDERPATH_SOFT:
6190         case RENDERPATH_GLES2:
6191                 permutation =
6192                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6193                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6194                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6195                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6196                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6197
6198                 if (r_bloomstate.texture_screen)
6199                 {
6200                         // make sure the buffer is available
6201                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6202
6203                         R_ResetViewRendering2D();
6204                         R_Mesh_SetMainRenderTargets();
6205
6206                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6207                         {
6208                                 // declare variables
6209                                 float speed;
6210                                 static float avgspeed;
6211
6212                                 speed = VectorLength(cl.movement_velocity);
6213
6214                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6215                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6216
6217                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6218                                 speed = bound(0, speed, 1);
6219                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6220
6221                                 // calculate values into a standard alpha
6222                                 cl.motionbluralpha = 1 - exp(-
6223                                                 (
6224                                                  (r_motionblur.value * speed / 80)
6225                                                  +
6226                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6227                                                 )
6228                                                 /
6229                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6230                                            );
6231
6232                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6233                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6234                                 // apply the blur
6235                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6236                                 {
6237                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6238                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6239                                         switch(vid.renderpath)
6240                                         {
6241                                         case RENDERPATH_GL11:
6242                                         case RENDERPATH_GL13:
6243                                         case RENDERPATH_GL20:
6244                                         case RENDERPATH_GLES1:
6245                                         case RENDERPATH_GLES2:
6246                                         case RENDERPATH_SOFT:
6247                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6248                                                 break;
6249                                         case RENDERPATH_D3D9:
6250                                         case RENDERPATH_D3D10:
6251                                         case RENDERPATH_D3D11:
6252                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6253                                                 break;
6254                                         }
6255                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6256                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6257                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6258                                 }
6259                         }
6260
6261                         // copy view into the screen texture
6262                         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);
6263                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6264                 }
6265                 else if (!r_bloomstate.texture_bloom)
6266                 {
6267                         // we may still have to do view tint...
6268                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6269                         {
6270                                 // apply a color tint to the whole view
6271                                 R_ResetViewRendering2D();
6272                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6273                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6274                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6275                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6276                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6277                         }
6278                         break; // no screen processing, no bloom, skip it
6279                 }
6280
6281                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6282                 {
6283                         // render simple bloom effect
6284                         // copy the screen and shrink it and darken it for the bloom process
6285                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6286                         // make the bloom texture
6287                         R_Bloom_MakeTexture();
6288                 }
6289
6290 #if _MSC_VER >= 1400
6291 #define sscanf sscanf_s
6292 #endif
6293                 memset(uservecs, 0, sizeof(uservecs));
6294                 if (r_glsl_postprocess_uservec1_enable.integer)
6295                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6296                 if (r_glsl_postprocess_uservec2_enable.integer)
6297                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6298                 if (r_glsl_postprocess_uservec3_enable.integer)
6299                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6300                 if (r_glsl_postprocess_uservec4_enable.integer)
6301                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6302
6303                 R_ResetViewRendering2D();
6304                 GL_Color(1, 1, 1, 1);
6305                 GL_BlendFunc(GL_ONE, GL_ZERO);
6306
6307                 switch(vid.renderpath)
6308                 {
6309                 case RENDERPATH_GL20:
6310                 case RENDERPATH_GLES2:
6311                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6312                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6313                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6314                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6315                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6316                         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]);
6317                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6318                         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]);
6319                         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]);
6320                         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]);
6321                         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]);
6322                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6323                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6324                         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);
6325                         break;
6326                 case RENDERPATH_D3D9:
6327 #ifdef SUPPORTD3D
6328                         // 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...
6329                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6330                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6331                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6332                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6333                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6334                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6335                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6336                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6337                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6338                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6339                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6340                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6341                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6342                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6343 #endif
6344                         break;
6345                 case RENDERPATH_D3D10:
6346                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6347                         break;
6348                 case RENDERPATH_D3D11:
6349                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6350                         break;
6351                 case RENDERPATH_SOFT:
6352                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6353                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6354                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6355                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6356                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6357                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6358                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6359                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6360                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6361                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6362                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6363                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6364                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6365                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6366                         break;
6367                 default:
6368                         break;
6369                 }
6370                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6371                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6372                 break;
6373         case RENDERPATH_GL11:
6374         case RENDERPATH_GL13:
6375         case RENDERPATH_GLES1:
6376                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6377                 {
6378                         // apply a color tint to the whole view
6379                         R_ResetViewRendering2D();
6380                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6381                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6382                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6383                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6384                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6385                 }
6386                 break;
6387         }
6388 }
6389
6390 matrix4x4_t r_waterscrollmatrix;
6391
6392 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6393 {
6394         if (r_refdef.fog_density)
6395         {
6396                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6397                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6398                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6399
6400                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6401                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6402                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6403                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6404
6405                 {
6406                         vec3_t fogvec;
6407                         VectorCopy(r_refdef.fogcolor, fogvec);
6408                         //   color.rgb *= ContrastBoost * SceneBrightness;
6409                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6410                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6411                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6412                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6413                 }
6414         }
6415 }
6416
6417 void R_UpdateVariables(void)
6418 {
6419         R_Textures_Frame();
6420
6421         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6422
6423         r_refdef.farclip = r_farclip_base.value;
6424         if (r_refdef.scene.worldmodel)
6425                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6426         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6427
6428         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6429                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6430         r_refdef.polygonfactor = 0;
6431         r_refdef.polygonoffset = 0;
6432         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6433         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6434
6435         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6436         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6437         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6438         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6439         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6440         if (FAKELIGHT_ENABLED)
6441         {
6442                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6443         }
6444         if (r_showsurfaces.integer)
6445         {
6446                 r_refdef.scene.rtworld = false;
6447                 r_refdef.scene.rtworldshadows = false;
6448                 r_refdef.scene.rtdlight = false;
6449                 r_refdef.scene.rtdlightshadows = false;
6450                 r_refdef.lightmapintensity = 0;
6451         }
6452
6453         if (gamemode == GAME_NEHAHRA)
6454         {
6455                 if (gl_fogenable.integer)
6456                 {
6457                         r_refdef.oldgl_fogenable = true;
6458                         r_refdef.fog_density = gl_fogdensity.value;
6459                         r_refdef.fog_red = gl_fogred.value;
6460                         r_refdef.fog_green = gl_foggreen.value;
6461                         r_refdef.fog_blue = gl_fogblue.value;
6462                         r_refdef.fog_alpha = 1;
6463                         r_refdef.fog_start = 0;
6464                         r_refdef.fog_end = gl_skyclip.value;
6465                         r_refdef.fog_height = 1<<30;
6466                         r_refdef.fog_fadedepth = 128;
6467                 }
6468                 else if (r_refdef.oldgl_fogenable)
6469                 {
6470                         r_refdef.oldgl_fogenable = false;
6471                         r_refdef.fog_density = 0;
6472                         r_refdef.fog_red = 0;
6473                         r_refdef.fog_green = 0;
6474                         r_refdef.fog_blue = 0;
6475                         r_refdef.fog_alpha = 0;
6476                         r_refdef.fog_start = 0;
6477                         r_refdef.fog_end = 0;
6478                         r_refdef.fog_height = 1<<30;
6479                         r_refdef.fog_fadedepth = 128;
6480                 }
6481         }
6482
6483         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6484         r_refdef.fog_start = max(0, r_refdef.fog_start);
6485         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6486
6487         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6488
6489         if (r_refdef.fog_density && r_drawfog.integer)
6490         {
6491                 r_refdef.fogenabled = true;
6492                 // this is the point where the fog reaches 0.9986 alpha, which we
6493                 // consider a good enough cutoff point for the texture
6494                 // (0.9986 * 256 == 255.6)
6495                 if (r_fog_exp2.integer)
6496                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6497                 else
6498                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6499                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6500                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6501                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6502                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6503                         R_BuildFogHeightTexture();
6504                 // fog color was already set
6505                 // update the fog texture
6506                 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)
6507                         R_BuildFogTexture();
6508                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6509                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6510         }
6511         else
6512                 r_refdef.fogenabled = false;
6513
6514         switch(vid.renderpath)
6515         {
6516         case RENDERPATH_GL20:
6517         case RENDERPATH_D3D9:
6518         case RENDERPATH_D3D10:
6519         case RENDERPATH_D3D11:
6520         case RENDERPATH_SOFT:
6521         case RENDERPATH_GLES2:
6522                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6523                 {
6524                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6525                         {
6526                                 // build GLSL gamma texture
6527 #define RAMPWIDTH 256
6528                                 unsigned short ramp[RAMPWIDTH * 3];
6529                                 unsigned char rampbgr[RAMPWIDTH][4];
6530                                 int i;
6531
6532                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6533
6534                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6535                                 for(i = 0; i < RAMPWIDTH; ++i)
6536                                 {
6537                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6538                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6539                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6540                                         rampbgr[i][3] = 0;
6541                                 }
6542                                 if (r_texture_gammaramps)
6543                                 {
6544                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6545                                 }
6546                                 else
6547                                 {
6548                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6549                                 }
6550                         }
6551                 }
6552                 else
6553                 {
6554                         // remove GLSL gamma texture
6555                 }
6556                 break;
6557         case RENDERPATH_GL11:
6558         case RENDERPATH_GL13:
6559         case RENDERPATH_GLES1:
6560                 break;
6561         }
6562 }
6563
6564 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6565 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6566 /*
6567 ================
6568 R_SelectScene
6569 ================
6570 */
6571 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6572         if( scenetype != r_currentscenetype ) {
6573                 // store the old scenetype
6574                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6575                 r_currentscenetype = scenetype;
6576                 // move in the new scene
6577                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6578         }
6579 }
6580
6581 /*
6582 ================
6583 R_GetScenePointer
6584 ================
6585 */
6586 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6587 {
6588         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6589         if( scenetype == r_currentscenetype ) {
6590                 return &r_refdef.scene;
6591         } else {
6592                 return &r_scenes_store[ scenetype ];
6593         }
6594 }
6595
6596 /*
6597 ================
6598 R_RenderView
6599 ================
6600 */
6601 int dpsoftrast_test;
6602 void R_RenderView(void)
6603 {
6604         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6605
6606         dpsoftrast_test = r_test.integer;
6607
6608         if (r_timereport_active)
6609                 R_TimeReport("start");
6610         r_textureframe++; // used only by R_GetCurrentTexture
6611         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6612
6613         if(R_CompileShader_CheckStaticParms())
6614                 R_GLSL_Restart_f();
6615
6616         if (!r_drawentities.integer)
6617                 r_refdef.scene.numentities = 0;
6618
6619         R_AnimCache_ClearCache();
6620         R_FrameData_NewFrame();
6621
6622         /* adjust for stereo display */
6623         if(R_Stereo_Active())
6624         {
6625                 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);
6626                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6627         }
6628
6629         if (r_refdef.view.isoverlay)
6630         {
6631                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6632                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6633                 R_TimeReport("depthclear");
6634
6635                 r_refdef.view.showdebug = false;
6636
6637                 r_waterstate.enabled = false;
6638                 r_waterstate.numwaterplanes = 0;
6639
6640                 R_RenderScene();
6641
6642                 r_refdef.view.matrix = originalmatrix;
6643
6644                 CHECKGLERROR
6645                 return;
6646         }
6647
6648         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6649         {
6650                 r_refdef.view.matrix = originalmatrix;
6651                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6652         }
6653
6654         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6655
6656         R_RenderView_UpdateViewVectors();
6657
6658         R_Shadow_UpdateWorldLightSelection();
6659
6660         R_Bloom_StartFrame();
6661         R_Water_StartFrame();
6662
6663         CHECKGLERROR
6664         if (r_timereport_active)
6665                 R_TimeReport("viewsetup");
6666
6667         R_ResetViewRendering3D();
6668
6669         if (r_refdef.view.clear || r_refdef.fogenabled)
6670         {
6671                 R_ClearScreen(r_refdef.fogenabled);
6672                 if (r_timereport_active)
6673                         R_TimeReport("viewclear");
6674         }
6675         r_refdef.view.clear = true;
6676
6677         // this produces a bloom texture to be used in R_BlendView() later
6678         if (r_bloomstate.hdr)
6679         {
6680                 R_HDR_RenderBloomTexture();
6681                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6682                 r_textureframe++; // used only by R_GetCurrentTexture
6683         }
6684
6685         r_refdef.view.showdebug = true;
6686
6687         R_View_Update();
6688         if (r_timereport_active)
6689                 R_TimeReport("visibility");
6690
6691         r_waterstate.numwaterplanes = 0;
6692         if (r_waterstate.enabled)
6693                 R_RenderWaterPlanes();
6694
6695         R_RenderScene();
6696         r_waterstate.numwaterplanes = 0;
6697
6698         R_BlendView();
6699         if (r_timereport_active)
6700                 R_TimeReport("blendview");
6701
6702         GL_Scissor(0, 0, vid.width, vid.height);
6703         GL_ScissorTest(false);
6704
6705         r_refdef.view.matrix = originalmatrix;
6706
6707         CHECKGLERROR
6708 }
6709
6710 void R_RenderWaterPlanes(void)
6711 {
6712         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6713         {
6714                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6715                 if (r_timereport_active)
6716                         R_TimeReport("waterworld");
6717         }
6718
6719         // don't let sound skip if going slow
6720         if (r_refdef.scene.extraupdate)
6721                 S_ExtraUpdate ();
6722
6723         R_DrawModelsAddWaterPlanes();
6724         if (r_timereport_active)
6725                 R_TimeReport("watermodels");
6726
6727         if (r_waterstate.numwaterplanes)
6728         {
6729                 R_Water_ProcessPlanes();
6730                 if (r_timereport_active)
6731                         R_TimeReport("waterscenes");
6732         }
6733 }
6734
6735 extern void R_DrawLightningBeams (void);
6736 extern void VM_CL_AddPolygonsToMeshQueue (void);
6737 extern void R_DrawPortals (void);
6738 extern cvar_t cl_locs_show;
6739 static void R_DrawLocs(void);
6740 static void R_DrawEntityBBoxes(void);
6741 static void R_DrawModelDecals(void);
6742 extern void R_DrawModelShadows(void);
6743 extern void R_DrawModelShadowMaps(void);
6744 extern cvar_t cl_decals_newsystem;
6745 extern qboolean r_shadow_usingdeferredprepass;
6746 void R_RenderScene(void)
6747 {
6748         qboolean shadowmapping = false;
6749
6750         if (r_timereport_active)
6751                 R_TimeReport("beginscene");
6752
6753         r_refdef.stats.renders++;
6754
6755         R_UpdateFogColor();
6756
6757         // don't let sound skip if going slow
6758         if (r_refdef.scene.extraupdate)
6759                 S_ExtraUpdate ();
6760
6761         R_MeshQueue_BeginScene();
6762
6763         R_SkyStartFrame();
6764
6765         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);
6766
6767         if (r_timereport_active)
6768                 R_TimeReport("skystartframe");
6769
6770         if (cl.csqc_vidvars.drawworld)
6771         {
6772                 // don't let sound skip if going slow
6773                 if (r_refdef.scene.extraupdate)
6774                         S_ExtraUpdate ();
6775
6776                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6777                 {
6778                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6779                         if (r_timereport_active)
6780                                 R_TimeReport("worldsky");
6781                 }
6782
6783                 if (R_DrawBrushModelsSky() && r_timereport_active)
6784                         R_TimeReport("bmodelsky");
6785
6786                 if (skyrendermasked && skyrenderlater)
6787                 {
6788                         // we have to force off the water clipping plane while rendering sky
6789                         R_SetupView(false);
6790                         R_Sky();
6791                         R_SetupView(true);
6792                         if (r_timereport_active)
6793                                 R_TimeReport("sky");
6794                 }
6795         }
6796
6797         R_AnimCache_CacheVisibleEntities();
6798         if (r_timereport_active)
6799                 R_TimeReport("animation");
6800
6801         R_Shadow_PrepareLights();
6802         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6803                 R_Shadow_PrepareModelShadows();
6804         if (r_timereport_active)
6805                 R_TimeReport("preparelights");
6806
6807         if (R_Shadow_ShadowMappingEnabled())
6808                 shadowmapping = true;
6809
6810         if (r_shadow_usingdeferredprepass)
6811                 R_Shadow_DrawPrepass();
6812
6813         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6814         {
6815                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6816                 if (r_timereport_active)
6817                         R_TimeReport("worlddepth");
6818         }
6819         if (r_depthfirst.integer >= 2)
6820         {
6821                 R_DrawModelsDepth();
6822                 if (r_timereport_active)
6823                         R_TimeReport("modeldepth");
6824         }
6825
6826         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6827         {
6828                 R_DrawModelShadowMaps();
6829                 R_ResetViewRendering3D();
6830                 // don't let sound skip if going slow
6831                 if (r_refdef.scene.extraupdate)
6832                         S_ExtraUpdate ();
6833         }
6834
6835         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6836         {
6837                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6838                 if (r_timereport_active)
6839                         R_TimeReport("world");
6840         }
6841
6842         // don't let sound skip if going slow
6843         if (r_refdef.scene.extraupdate)
6844                 S_ExtraUpdate ();
6845
6846         R_DrawModels();
6847         if (r_timereport_active)
6848                 R_TimeReport("models");
6849
6850         // don't let sound skip if going slow
6851         if (r_refdef.scene.extraupdate)
6852                 S_ExtraUpdate ();
6853
6854         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6855         {
6856                 R_DrawModelShadows();
6857                 R_ResetViewRendering3D();
6858                 // don't let sound skip if going slow
6859                 if (r_refdef.scene.extraupdate)
6860                         S_ExtraUpdate ();
6861         }
6862
6863         if (!r_shadow_usingdeferredprepass)
6864         {
6865                 R_Shadow_DrawLights();
6866                 if (r_timereport_active)
6867                         R_TimeReport("rtlights");
6868         }
6869
6870         // don't let sound skip if going slow
6871         if (r_refdef.scene.extraupdate)
6872                 S_ExtraUpdate ();
6873
6874         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6875         {
6876                 R_DrawModelShadows();
6877                 R_ResetViewRendering3D();
6878                 // don't let sound skip if going slow
6879                 if (r_refdef.scene.extraupdate)
6880                         S_ExtraUpdate ();
6881         }
6882
6883         if (cl.csqc_vidvars.drawworld)
6884         {
6885                 if (cl_decals_newsystem.integer)
6886                 {
6887                         R_DrawModelDecals();
6888                         if (r_timereport_active)
6889                                 R_TimeReport("modeldecals");
6890                 }
6891                 else
6892                 {
6893                         R_DrawDecals();
6894                         if (r_timereport_active)
6895                                 R_TimeReport("decals");
6896                 }
6897
6898                 R_DrawParticles();
6899                 if (r_timereport_active)
6900                         R_TimeReport("particles");
6901
6902                 R_DrawExplosions();
6903                 if (r_timereport_active)
6904                         R_TimeReport("explosions");
6905
6906                 R_DrawLightningBeams();
6907                 if (r_timereport_active)
6908                         R_TimeReport("lightning");
6909         }
6910
6911         VM_CL_AddPolygonsToMeshQueue();
6912
6913         if (r_refdef.view.showdebug)
6914         {
6915                 if (cl_locs_show.integer)
6916                 {
6917                         R_DrawLocs();
6918                         if (r_timereport_active)
6919                                 R_TimeReport("showlocs");
6920                 }
6921
6922                 if (r_drawportals.integer)
6923                 {
6924                         R_DrawPortals();
6925                         if (r_timereport_active)
6926                                 R_TimeReport("portals");
6927                 }
6928
6929                 if (r_showbboxes.value > 0)
6930                 {
6931                         R_DrawEntityBBoxes();
6932                         if (r_timereport_active)
6933                                 R_TimeReport("bboxes");
6934                 }
6935         }
6936
6937         if (r_transparent.integer)
6938         {
6939                 R_MeshQueue_RenderTransparent();
6940                 if (r_timereport_active)
6941                         R_TimeReport("drawtrans");
6942         }
6943
6944         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))
6945         {
6946                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6947                 if (r_timereport_active)
6948                         R_TimeReport("worlddebug");
6949                 R_DrawModelsDebug();
6950                 if (r_timereport_active)
6951                         R_TimeReport("modeldebug");
6952         }
6953
6954         if (cl.csqc_vidvars.drawworld)
6955         {
6956                 R_Shadow_DrawCoronas();
6957                 if (r_timereport_active)
6958                         R_TimeReport("coronas");
6959         }
6960
6961 #if 0
6962         {
6963                 GL_DepthTest(false);
6964                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6965                 GL_Color(1, 1, 1, 1);
6966                 qglBegin(GL_POLYGON);
6967                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6968                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6969                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6970                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6971                 qglEnd();
6972                 qglBegin(GL_POLYGON);
6973                 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]);
6974                 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]);
6975                 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]);
6976                 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]);
6977                 qglEnd();
6978                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6979         }
6980 #endif
6981
6982         // don't let sound skip if going slow
6983         if (r_refdef.scene.extraupdate)
6984                 S_ExtraUpdate ();
6985
6986         R_ResetViewRendering2D();
6987 }
6988
6989 static const unsigned short bboxelements[36] =
6990 {
6991         5, 1, 3, 5, 3, 7,
6992         6, 2, 0, 6, 0, 4,
6993         7, 3, 2, 7, 2, 6,
6994         4, 0, 1, 4, 1, 5,
6995         4, 5, 7, 4, 7, 6,
6996         1, 0, 2, 1, 2, 3,
6997 };
6998
6999 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7000 {
7001         int i;
7002         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7003
7004         RSurf_ActiveWorldEntity();
7005
7006         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7007         GL_DepthMask(false);
7008         GL_DepthRange(0, 1);
7009         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7010 //      R_Mesh_ResetTextureState();
7011
7012         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7013         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7014         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7015         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7016         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7017         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7018         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7019         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7020         R_FillColors(color4f, 8, cr, cg, cb, ca);
7021         if (r_refdef.fogenabled)
7022         {
7023                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7024                 {
7025                         f1 = RSurf_FogVertex(v);
7026                         f2 = 1 - f1;
7027                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7028                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7029                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7030                 }
7031         }
7032         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7033         R_Mesh_ResetTextureState();
7034         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7035         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7036 }
7037
7038 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7039 {
7040         int i;
7041         float color[4];
7042         prvm_edict_t *edict;
7043         prvm_prog_t *prog_save = prog;
7044
7045         // this function draws bounding boxes of server entities
7046         if (!sv.active)
7047                 return;
7048
7049         GL_CullFace(GL_NONE);
7050         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7051
7052         prog = 0;
7053         SV_VM_Begin();
7054         for (i = 0;i < numsurfaces;i++)
7055         {
7056                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7057                 switch ((int)edict->fields.server->solid)
7058                 {
7059                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7060                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7061                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7062                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7063                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7064                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7065                 }
7066                 color[3] *= r_showbboxes.value;
7067                 color[3] = bound(0, color[3], 1);
7068                 GL_DepthTest(!r_showdisabledepthtest.integer);
7069                 GL_CullFace(r_refdef.view.cullface_front);
7070                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7071         }
7072         SV_VM_End();
7073         prog = prog_save;
7074 }
7075
7076 static void R_DrawEntityBBoxes(void)
7077 {
7078         int i;
7079         prvm_edict_t *edict;
7080         vec3_t center;
7081         prvm_prog_t *prog_save = prog;
7082
7083         // this function draws bounding boxes of server entities
7084         if (!sv.active)
7085                 return;
7086
7087         prog = 0;
7088         SV_VM_Begin();
7089         for (i = 0;i < prog->num_edicts;i++)
7090         {
7091                 edict = PRVM_EDICT_NUM(i);
7092                 if (edict->priv.server->free)
7093                         continue;
7094                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7095                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7096                         continue;
7097                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7098                         continue;
7099                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7100                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7101         }
7102         SV_VM_End();
7103         prog = prog_save;
7104 }
7105
7106 static const int nomodelelement3i[24] =
7107 {
7108         5, 2, 0,
7109         5, 1, 2,
7110         5, 0, 3,
7111         5, 3, 1,
7112         0, 2, 4,
7113         2, 1, 4,
7114         3, 0, 4,
7115         1, 3, 4
7116 };
7117
7118 static const unsigned short nomodelelement3s[24] =
7119 {
7120         5, 2, 0,
7121         5, 1, 2,
7122         5, 0, 3,
7123         5, 3, 1,
7124         0, 2, 4,
7125         2, 1, 4,
7126         3, 0, 4,
7127         1, 3, 4
7128 };
7129
7130 static const float nomodelvertex3f[6*3] =
7131 {
7132         -16,   0,   0,
7133          16,   0,   0,
7134           0, -16,   0,
7135           0,  16,   0,
7136           0,   0, -16,
7137           0,   0,  16
7138 };
7139
7140 static const float nomodelcolor4f[6*4] =
7141 {
7142         0.0f, 0.0f, 0.5f, 1.0f,
7143         0.0f, 0.0f, 0.5f, 1.0f,
7144         0.0f, 0.5f, 0.0f, 1.0f,
7145         0.0f, 0.5f, 0.0f, 1.0f,
7146         0.5f, 0.0f, 0.0f, 1.0f,
7147         0.5f, 0.0f, 0.0f, 1.0f
7148 };
7149
7150 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7151 {
7152         int i;
7153         float f1, f2, *c;
7154         float color4f[6*4];
7155
7156         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);
7157
7158         // this is only called once per entity so numsurfaces is always 1, and
7159         // surfacelist is always {0}, so this code does not handle batches
7160
7161         if (rsurface.ent_flags & RENDER_ADDITIVE)
7162         {
7163                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7164                 GL_DepthMask(false);
7165         }
7166         else if (rsurface.colormod[3] < 1)
7167         {
7168                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7169                 GL_DepthMask(false);
7170         }
7171         else
7172         {
7173                 GL_BlendFunc(GL_ONE, GL_ZERO);
7174                 GL_DepthMask(true);
7175         }
7176         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7177         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7178         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7179         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7180         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7181         for (i = 0, c = color4f;i < 6;i++, c += 4)
7182         {
7183                 c[0] *= rsurface.colormod[0];
7184                 c[1] *= rsurface.colormod[1];
7185                 c[2] *= rsurface.colormod[2];
7186                 c[3] *= rsurface.colormod[3];
7187         }
7188         if (r_refdef.fogenabled)
7189         {
7190                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7191                 {
7192                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7193                         f2 = 1 - f1;
7194                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7195                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7196                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7197                 }
7198         }
7199 //      R_Mesh_ResetTextureState();
7200         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7201         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7202         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7203 }
7204
7205 void R_DrawNoModel(entity_render_t *ent)
7206 {
7207         vec3_t org;
7208         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7209         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7210                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7211         else
7212                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7213 }
7214
7215 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7216 {
7217         vec3_t right1, right2, diff, normal;
7218
7219         VectorSubtract (org2, org1, normal);
7220
7221         // calculate 'right' vector for start
7222         VectorSubtract (r_refdef.view.origin, org1, diff);
7223         CrossProduct (normal, diff, right1);
7224         VectorNormalize (right1);
7225
7226         // calculate 'right' vector for end
7227         VectorSubtract (r_refdef.view.origin, org2, diff);
7228         CrossProduct (normal, diff, right2);
7229         VectorNormalize (right2);
7230
7231         vert[ 0] = org1[0] + width * right1[0];
7232         vert[ 1] = org1[1] + width * right1[1];
7233         vert[ 2] = org1[2] + width * right1[2];
7234         vert[ 3] = org1[0] - width * right1[0];
7235         vert[ 4] = org1[1] - width * right1[1];
7236         vert[ 5] = org1[2] - width * right1[2];
7237         vert[ 6] = org2[0] - width * right2[0];
7238         vert[ 7] = org2[1] - width * right2[1];
7239         vert[ 8] = org2[2] - width * right2[2];
7240         vert[ 9] = org2[0] + width * right2[0];
7241         vert[10] = org2[1] + width * right2[1];
7242         vert[11] = org2[2] + width * right2[2];
7243 }
7244
7245 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)
7246 {
7247         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7248         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7249         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7250         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7251         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7252         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7253         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7254         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7255         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7256         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7257         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7258         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7259 }
7260
7261 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7262 {
7263         int i;
7264         float *vertex3f;
7265         float v[3];
7266         VectorSet(v, x, y, z);
7267         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7268                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7269                         break;
7270         if (i == mesh->numvertices)
7271         {
7272                 if (mesh->numvertices < mesh->maxvertices)
7273                 {
7274                         VectorCopy(v, vertex3f);
7275                         mesh->numvertices++;
7276                 }
7277                 return mesh->numvertices;
7278         }
7279         else
7280                 return i;
7281 }
7282
7283 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7284 {
7285         int i;
7286         int *e, element[3];
7287         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7288         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7289         e = mesh->element3i + mesh->numtriangles * 3;
7290         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7291         {
7292                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7293                 if (mesh->numtriangles < mesh->maxtriangles)
7294                 {
7295                         *e++ = element[0];
7296                         *e++ = element[1];
7297                         *e++ = element[2];
7298                         mesh->numtriangles++;
7299                 }
7300                 element[1] = element[2];
7301         }
7302 }
7303
7304 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7305 {
7306         int i;
7307         int *e, element[3];
7308         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7309         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7310         e = mesh->element3i + mesh->numtriangles * 3;
7311         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7312         {
7313                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7314                 if (mesh->numtriangles < mesh->maxtriangles)
7315                 {
7316                         *e++ = element[0];
7317                         *e++ = element[1];
7318                         *e++ = element[2];
7319                         mesh->numtriangles++;
7320                 }
7321                 element[1] = element[2];
7322         }
7323 }
7324
7325 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7326 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7327 {
7328         int planenum, planenum2;
7329         int w;
7330         int tempnumpoints;
7331         mplane_t *plane, *plane2;
7332         double maxdist;
7333         double temppoints[2][256*3];
7334         // figure out how large a bounding box we need to properly compute this brush
7335         maxdist = 0;
7336         for (w = 0;w < numplanes;w++)
7337                 maxdist = max(maxdist, fabs(planes[w].dist));
7338         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7339         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7340         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7341         {
7342                 w = 0;
7343                 tempnumpoints = 4;
7344                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7345                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7346                 {
7347                         if (planenum2 == planenum)
7348                                 continue;
7349                         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);
7350                         w = !w;
7351                 }
7352                 if (tempnumpoints < 3)
7353                         continue;
7354                 // generate elements forming a triangle fan for this polygon
7355                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7356         }
7357 }
7358
7359 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)
7360 {
7361         texturelayer_t *layer;
7362         layer = t->currentlayers + t->currentnumlayers++;
7363         layer->type = type;
7364         layer->depthmask = depthmask;
7365         layer->blendfunc1 = blendfunc1;
7366         layer->blendfunc2 = blendfunc2;
7367         layer->texture = texture;
7368         layer->texmatrix = *matrix;
7369         layer->color[0] = r;
7370         layer->color[1] = g;
7371         layer->color[2] = b;
7372         layer->color[3] = a;
7373 }
7374
7375 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7376 {
7377         if(parms[0] == 0 && parms[1] == 0)
7378                 return false;
7379         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7380                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7381                         return false;
7382         return true;
7383 }
7384
7385 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7386 {
7387         double index, f;
7388         index = parms[2] + r_refdef.scene.time * parms[3];
7389         index -= floor(index);
7390         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7391         {
7392         default:
7393         case Q3WAVEFUNC_NONE:
7394         case Q3WAVEFUNC_NOISE:
7395         case Q3WAVEFUNC_COUNT:
7396                 f = 0;
7397                 break;
7398         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7399         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7400         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7401         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7402         case Q3WAVEFUNC_TRIANGLE:
7403                 index *= 4;
7404                 f = index - floor(index);
7405                 if (index < 1)
7406                         f = f;
7407                 else if (index < 2)
7408                         f = 1 - f;
7409                 else if (index < 3)
7410                         f = -f;
7411                 else
7412                         f = -(1 - f);
7413                 break;
7414         }
7415         f = parms[0] + parms[1] * f;
7416         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7417                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7418         return (float) f;
7419 }
7420
7421 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7422 {
7423         int w, h, idx;
7424         float f;
7425         float tcmat[12];
7426         matrix4x4_t matrix, temp;
7427         switch(tcmod->tcmod)
7428         {
7429                 case Q3TCMOD_COUNT:
7430                 case Q3TCMOD_NONE:
7431                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7432                                 matrix = r_waterscrollmatrix;
7433                         else
7434                                 matrix = identitymatrix;
7435                         break;
7436                 case Q3TCMOD_ENTITYTRANSLATE:
7437                         // this is used in Q3 to allow the gamecode to control texcoord
7438                         // scrolling on the entity, which is not supported in darkplaces yet.
7439                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7440                         break;
7441                 case Q3TCMOD_ROTATE:
7442                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7443                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7444                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7445                         break;
7446                 case Q3TCMOD_SCALE:
7447                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7448                         break;
7449                 case Q3TCMOD_SCROLL:
7450                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7451                         break;
7452                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7453                         w = (int) tcmod->parms[0];
7454                         h = (int) tcmod->parms[1];
7455                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7456                         f = f - floor(f);
7457                         idx = (int) floor(f * w * h);
7458                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7459                         break;
7460                 case Q3TCMOD_STRETCH:
7461                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7462                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7463                         break;
7464                 case Q3TCMOD_TRANSFORM:
7465                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7466                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7467                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7468                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7469                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7470                         break;
7471                 case Q3TCMOD_TURBULENT:
7472                         // this is handled in the RSurf_PrepareVertices function
7473                         matrix = identitymatrix;
7474                         break;
7475         }
7476         temp = *texmatrix;
7477         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7478 }
7479
7480 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7481 {
7482         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7483         char name[MAX_QPATH];
7484         skinframe_t *skinframe;
7485         unsigned char pixels[296*194];
7486         strlcpy(cache->name, skinname, sizeof(cache->name));
7487         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7488         if (developer_loading.integer)
7489                 Con_Printf("loading %s\n", name);
7490         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7491         if (!skinframe || !skinframe->base)
7492         {
7493                 unsigned char *f;
7494                 fs_offset_t filesize;
7495                 skinframe = NULL;
7496                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7497                 if (f)
7498                 {
7499                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7500                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7501                         Mem_Free(f);
7502                 }
7503         }
7504         cache->skinframe = skinframe;
7505 }
7506
7507 texture_t *R_GetCurrentTexture(texture_t *t)
7508 {
7509         int i;
7510         const entity_render_t *ent = rsurface.entity;
7511         dp_model_t *model = ent->model;
7512         q3shaderinfo_layer_tcmod_t *tcmod;
7513
7514         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7515                 return t->currentframe;
7516         t->update_lastrenderframe = r_textureframe;
7517         t->update_lastrenderentity = (void *)ent;
7518
7519         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7520                 t->camera_entity = ent->entitynumber;
7521         else
7522                 t->camera_entity = 0;
7523
7524         // switch to an alternate material if this is a q1bsp animated material
7525         {
7526                 texture_t *texture = t;
7527                 int s = rsurface.ent_skinnum;
7528                 if ((unsigned int)s >= (unsigned int)model->numskins)
7529                         s = 0;
7530                 if (model->skinscenes)
7531                 {
7532                         if (model->skinscenes[s].framecount > 1)
7533                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7534                         else
7535                                 s = model->skinscenes[s].firstframe;
7536                 }
7537                 if (s > 0)
7538                         t = t + s * model->num_surfaces;
7539                 if (t->animated)
7540                 {
7541                         // use an alternate animation if the entity's frame is not 0,
7542                         // and only if the texture has an alternate animation
7543                         if (rsurface.ent_alttextures && t->anim_total[1])
7544                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7545                         else
7546                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7547                 }
7548                 texture->currentframe = t;
7549         }
7550
7551         // update currentskinframe to be a qw skin or animation frame
7552         if (rsurface.ent_qwskin >= 0)
7553         {
7554                 i = rsurface.ent_qwskin;
7555                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7556                 {
7557                         r_qwskincache_size = cl.maxclients;
7558                         if (r_qwskincache)
7559                                 Mem_Free(r_qwskincache);
7560                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7561                 }
7562                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7563                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7564                 t->currentskinframe = r_qwskincache[i].skinframe;
7565                 if (t->currentskinframe == NULL)
7566                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7567         }
7568         else if (t->numskinframes >= 2)
7569                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7570         if (t->backgroundnumskinframes >= 2)
7571                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7572
7573         t->currentmaterialflags = t->basematerialflags;
7574         t->currentalpha = rsurface.colormod[3];
7575         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7576                 t->currentalpha *= r_wateralpha.value;
7577         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7578                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7579         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7580                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7581         if (!(rsurface.ent_flags & RENDER_LIGHT))
7582                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7583         else if (FAKELIGHT_ENABLED)
7584         {
7585                 // no modellight if using fakelight for the map
7586         }
7587         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7588         {
7589                 // pick a model lighting mode
7590                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7591                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7592                 else
7593                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7594         }
7595         if (rsurface.ent_flags & RENDER_ADDITIVE)
7596                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7597         else if (t->currentalpha < 1)
7598                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7599         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7600                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7601         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7602                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7603         if (t->backgroundnumskinframes)
7604                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7605         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7606         {
7607                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7608                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7609         }
7610         else
7611                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7612         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7613                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7614
7615         // there is no tcmod
7616         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7617         {
7618                 t->currenttexmatrix = r_waterscrollmatrix;
7619                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7620         }
7621         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7622         {
7623                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7624                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7625         }
7626
7627         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7628                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7629         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7630                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7631
7632         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7633         if (t->currentskinframe->qpixels)
7634                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7635         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7636         if (!t->basetexture)
7637                 t->basetexture = r_texture_notexture;
7638         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7639         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7640         t->nmaptexture = t->currentskinframe->nmap;
7641         if (!t->nmaptexture)
7642                 t->nmaptexture = r_texture_blanknormalmap;
7643         t->glosstexture = r_texture_black;
7644         t->glowtexture = t->currentskinframe->glow;
7645         t->fogtexture = t->currentskinframe->fog;
7646         t->reflectmasktexture = t->currentskinframe->reflect;
7647         if (t->backgroundnumskinframes)
7648         {
7649                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7650                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7651                 t->backgroundglosstexture = r_texture_black;
7652                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7653                 if (!t->backgroundnmaptexture)
7654                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7655         }
7656         else
7657         {
7658                 t->backgroundbasetexture = r_texture_white;
7659                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7660                 t->backgroundglosstexture = r_texture_black;
7661                 t->backgroundglowtexture = NULL;
7662         }
7663         t->specularpower = r_shadow_glossexponent.value;
7664         // TODO: store reference values for these in the texture?
7665         t->specularscale = 0;
7666         if (r_shadow_gloss.integer > 0)
7667         {
7668                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7669                 {
7670                         if (r_shadow_glossintensity.value > 0)
7671                         {
7672                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7673                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7674                                 t->specularscale = r_shadow_glossintensity.value;
7675                         }
7676                 }
7677                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7678                 {
7679                         t->glosstexture = r_texture_white;
7680                         t->backgroundglosstexture = r_texture_white;
7681                         t->specularscale = r_shadow_gloss2intensity.value;
7682                         t->specularpower = r_shadow_gloss2exponent.value;
7683                 }
7684         }
7685         t->specularscale *= t->specularscalemod;
7686         t->specularpower *= t->specularpowermod;
7687
7688         // lightmaps mode looks bad with dlights using actual texturing, so turn
7689         // off the colormap and glossmap, but leave the normalmap on as it still
7690         // accurately represents the shading involved
7691         if (gl_lightmaps.integer)
7692         {
7693                 t->basetexture = r_texture_grey128;
7694                 t->pantstexture = r_texture_black;
7695                 t->shirttexture = r_texture_black;
7696                 t->nmaptexture = r_texture_blanknormalmap;
7697                 t->glosstexture = r_texture_black;
7698                 t->glowtexture = NULL;
7699                 t->fogtexture = NULL;
7700                 t->reflectmasktexture = NULL;
7701                 t->backgroundbasetexture = NULL;
7702                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7703                 t->backgroundglosstexture = r_texture_black;
7704                 t->backgroundglowtexture = NULL;
7705                 t->specularscale = 0;
7706                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7707         }
7708
7709         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7710         VectorClear(t->dlightcolor);
7711         t->currentnumlayers = 0;
7712         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7713         {
7714                 int blendfunc1, blendfunc2;
7715                 qboolean depthmask;
7716                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7717                 {
7718                         blendfunc1 = GL_SRC_ALPHA;
7719                         blendfunc2 = GL_ONE;
7720                 }
7721                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7722                 {
7723                         blendfunc1 = GL_SRC_ALPHA;
7724                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7725                 }
7726                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7727                 {
7728                         blendfunc1 = t->customblendfunc[0];
7729                         blendfunc2 = t->customblendfunc[1];
7730                 }
7731                 else
7732                 {
7733                         blendfunc1 = GL_ONE;
7734                         blendfunc2 = GL_ZERO;
7735                 }
7736                 // don't colormod evilblend textures
7737                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7738                         VectorSet(t->lightmapcolor, 1, 1, 1);
7739                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7740                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7741                 {
7742                         // fullbright is not affected by r_refdef.lightmapintensity
7743                         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]);
7744                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7745                                 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]);
7746                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7747                                 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]);
7748                 }
7749                 else
7750                 {
7751                         vec3_t ambientcolor;
7752                         float colorscale;
7753                         // set the color tint used for lights affecting this surface
7754                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7755                         colorscale = 2;
7756                         // q3bsp has no lightmap updates, so the lightstylevalue that
7757                         // would normally be baked into the lightmap must be
7758                         // applied to the color
7759                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7760                         if (model->type == mod_brushq3)
7761                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7762                         colorscale *= r_refdef.lightmapintensity;
7763                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7764                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7765                         // basic lit geometry
7766                         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]);
7767                         // add pants/shirt if needed
7768                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7769                                 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]);
7770                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7771                                 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]);
7772                         // now add ambient passes if needed
7773                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7774                         {
7775                                 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]);
7776                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7777                                         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]);
7778                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7779                                         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]);
7780                         }
7781                 }
7782                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7783                         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]);
7784                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7785                 {
7786                         // if this is opaque use alpha blend which will darken the earlier
7787                         // passes cheaply.
7788                         //
7789                         // if this is an alpha blended material, all the earlier passes
7790                         // were darkened by fog already, so we only need to add the fog
7791                         // color ontop through the fog mask texture
7792                         //
7793                         // if this is an additive blended material, all the earlier passes
7794                         // were darkened by fog already, and we should not add fog color
7795                         // (because the background was not darkened, there is no fog color
7796                         // that was lost behind it).
7797                         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]);
7798                 }
7799         }
7800
7801         return t->currentframe;
7802 }
7803
7804 rsurfacestate_t rsurface;
7805
7806 void RSurf_ActiveWorldEntity(void)
7807 {
7808         dp_model_t *model = r_refdef.scene.worldmodel;
7809         //if (rsurface.entity == r_refdef.scene.worldentity)
7810         //      return;
7811         rsurface.entity = r_refdef.scene.worldentity;
7812         rsurface.skeleton = NULL;
7813         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7814         rsurface.ent_skinnum = 0;
7815         rsurface.ent_qwskin = -1;
7816         rsurface.ent_shadertime = 0;
7817         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7818         rsurface.matrix = identitymatrix;
7819         rsurface.inversematrix = identitymatrix;
7820         rsurface.matrixscale = 1;
7821         rsurface.inversematrixscale = 1;
7822         R_EntityMatrix(&identitymatrix);
7823         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7824         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7825         rsurface.fograngerecip = r_refdef.fograngerecip;
7826         rsurface.fogheightfade = r_refdef.fogheightfade;
7827         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7828         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7829         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7830         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7831         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7832         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7833         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7834         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7835         rsurface.colormod[3] = 1;
7836         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);
7837         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7838         rsurface.frameblend[0].lerp = 1;
7839         rsurface.ent_alttextures = false;
7840         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7841         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7842         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7843         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7844         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7845         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7846         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7847         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7848         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7849         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7850         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7851         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7852         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7853         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7854         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7855         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7856         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7857         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7858         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7859         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7860         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7861         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7862         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7863         rsurface.modelelement3i = model->surfmesh.data_element3i;
7864         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7865         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7866         rsurface.modelelement3s = model->surfmesh.data_element3s;
7867         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7868         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7869         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7870         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7871         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7872         rsurface.modelsurfaces = model->data_surfaces;
7873         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7874         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7875         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7876         rsurface.modelgeneratedvertex = false;
7877         rsurface.batchgeneratedvertex = false;
7878         rsurface.batchfirstvertex = 0;
7879         rsurface.batchnumvertices = 0;
7880         rsurface.batchfirsttriangle = 0;
7881         rsurface.batchnumtriangles = 0;
7882         rsurface.batchvertex3f  = NULL;
7883         rsurface.batchvertex3f_vertexbuffer = NULL;
7884         rsurface.batchvertex3f_bufferoffset = 0;
7885         rsurface.batchsvector3f = NULL;
7886         rsurface.batchsvector3f_vertexbuffer = NULL;
7887         rsurface.batchsvector3f_bufferoffset = 0;
7888         rsurface.batchtvector3f = NULL;
7889         rsurface.batchtvector3f_vertexbuffer = NULL;
7890         rsurface.batchtvector3f_bufferoffset = 0;
7891         rsurface.batchnormal3f  = NULL;
7892         rsurface.batchnormal3f_vertexbuffer = NULL;
7893         rsurface.batchnormal3f_bufferoffset = 0;
7894         rsurface.batchlightmapcolor4f = NULL;
7895         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7896         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7897         rsurface.batchtexcoordtexture2f = NULL;
7898         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7899         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7900         rsurface.batchtexcoordlightmap2f = NULL;
7901         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7902         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7903         rsurface.batchvertexmesh = NULL;
7904         rsurface.batchvertexmeshbuffer = NULL;
7905         rsurface.batchvertex3fbuffer = NULL;
7906         rsurface.batchelement3i = NULL;
7907         rsurface.batchelement3i_indexbuffer = NULL;
7908         rsurface.batchelement3i_bufferoffset = 0;
7909         rsurface.batchelement3s = NULL;
7910         rsurface.batchelement3s_indexbuffer = NULL;
7911         rsurface.batchelement3s_bufferoffset = 0;
7912         rsurface.passcolor4f = NULL;
7913         rsurface.passcolor4f_vertexbuffer = NULL;
7914         rsurface.passcolor4f_bufferoffset = 0;
7915 }
7916
7917 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7918 {
7919         dp_model_t *model = ent->model;
7920         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7921         //      return;
7922         rsurface.entity = (entity_render_t *)ent;
7923         rsurface.skeleton = ent->skeleton;
7924         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7925         rsurface.ent_skinnum = ent->skinnum;
7926         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;
7927         rsurface.ent_shadertime = ent->shadertime;
7928         rsurface.ent_flags = ent->flags;
7929         rsurface.matrix = ent->matrix;
7930         rsurface.inversematrix = ent->inversematrix;
7931         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7932         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7933         R_EntityMatrix(&rsurface.matrix);
7934         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7935         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7936         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7937         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7938         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7939         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7940         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7941         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7942         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7943         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7944         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7945         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7946         rsurface.colormod[3] = ent->alpha;
7947         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7948         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7949         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7950         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7951         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7952         if (ent->model->brush.submodel && !prepass)
7953         {
7954                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7955                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7956         }
7957         if (model->surfmesh.isanimated && model->AnimateVertices)
7958         {
7959                 if (ent->animcache_vertex3f)
7960                 {
7961                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7962                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7963                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7964                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7965                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7966                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7967                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7968                 }
7969                 else if (wanttangents)
7970                 {
7971                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7972                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7973                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7974                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7975                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7976                         rsurface.modelvertexmesh = NULL;
7977                         rsurface.modelvertexmeshbuffer = NULL;
7978                         rsurface.modelvertex3fbuffer = NULL;
7979                 }
7980                 else if (wantnormals)
7981                 {
7982                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7983                         rsurface.modelsvector3f = NULL;
7984                         rsurface.modeltvector3f = NULL;
7985                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7986                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7987                         rsurface.modelvertexmesh = NULL;
7988                         rsurface.modelvertexmeshbuffer = NULL;
7989                         rsurface.modelvertex3fbuffer = NULL;
7990                 }
7991                 else
7992                 {
7993                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7994                         rsurface.modelsvector3f = NULL;
7995                         rsurface.modeltvector3f = NULL;
7996                         rsurface.modelnormal3f = NULL;
7997                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7998                         rsurface.modelvertexmesh = NULL;
7999                         rsurface.modelvertexmeshbuffer = NULL;
8000                         rsurface.modelvertex3fbuffer = NULL;
8001                 }
8002                 rsurface.modelvertex3f_vertexbuffer = 0;
8003                 rsurface.modelvertex3f_bufferoffset = 0;
8004                 rsurface.modelsvector3f_vertexbuffer = 0;
8005                 rsurface.modelsvector3f_bufferoffset = 0;
8006                 rsurface.modeltvector3f_vertexbuffer = 0;
8007                 rsurface.modeltvector3f_bufferoffset = 0;
8008                 rsurface.modelnormal3f_vertexbuffer = 0;
8009                 rsurface.modelnormal3f_bufferoffset = 0;
8010                 rsurface.modelgeneratedvertex = true;
8011         }
8012         else
8013         {
8014                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8015                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8016                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8017                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8018                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8019                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8020                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8021                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8022                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8023                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8024                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8025                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8026                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8027                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8028                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8029                 rsurface.modelgeneratedvertex = false;
8030         }
8031         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8032         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8033         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8034         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8035         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8036         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8037         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8038         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8039         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8040         rsurface.modelelement3i = model->surfmesh.data_element3i;
8041         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8042         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8043         rsurface.modelelement3s = model->surfmesh.data_element3s;
8044         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8045         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8046         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8047         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8048         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8049         rsurface.modelsurfaces = model->data_surfaces;
8050         rsurface.batchgeneratedvertex = false;
8051         rsurface.batchfirstvertex = 0;
8052         rsurface.batchnumvertices = 0;
8053         rsurface.batchfirsttriangle = 0;
8054         rsurface.batchnumtriangles = 0;
8055         rsurface.batchvertex3f  = NULL;
8056         rsurface.batchvertex3f_vertexbuffer = NULL;
8057         rsurface.batchvertex3f_bufferoffset = 0;
8058         rsurface.batchsvector3f = NULL;
8059         rsurface.batchsvector3f_vertexbuffer = NULL;
8060         rsurface.batchsvector3f_bufferoffset = 0;
8061         rsurface.batchtvector3f = NULL;
8062         rsurface.batchtvector3f_vertexbuffer = NULL;
8063         rsurface.batchtvector3f_bufferoffset = 0;
8064         rsurface.batchnormal3f  = NULL;
8065         rsurface.batchnormal3f_vertexbuffer = NULL;
8066         rsurface.batchnormal3f_bufferoffset = 0;
8067         rsurface.batchlightmapcolor4f = NULL;
8068         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8069         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8070         rsurface.batchtexcoordtexture2f = NULL;
8071         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8072         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8073         rsurface.batchtexcoordlightmap2f = NULL;
8074         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8075         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8076         rsurface.batchvertexmesh = NULL;
8077         rsurface.batchvertexmeshbuffer = NULL;
8078         rsurface.batchvertex3fbuffer = NULL;
8079         rsurface.batchelement3i = NULL;
8080         rsurface.batchelement3i_indexbuffer = NULL;
8081         rsurface.batchelement3i_bufferoffset = 0;
8082         rsurface.batchelement3s = NULL;
8083         rsurface.batchelement3s_indexbuffer = NULL;
8084         rsurface.batchelement3s_bufferoffset = 0;
8085         rsurface.passcolor4f = NULL;
8086         rsurface.passcolor4f_vertexbuffer = NULL;
8087         rsurface.passcolor4f_bufferoffset = 0;
8088 }
8089
8090 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)
8091 {
8092         rsurface.entity = r_refdef.scene.worldentity;
8093         rsurface.skeleton = NULL;
8094         rsurface.ent_skinnum = 0;
8095         rsurface.ent_qwskin = -1;
8096         rsurface.ent_shadertime = shadertime;
8097         rsurface.ent_flags = entflags;
8098         rsurface.modelnumvertices = numvertices;
8099         rsurface.modelnumtriangles = numtriangles;
8100         rsurface.matrix = *matrix;
8101         rsurface.inversematrix = *inversematrix;
8102         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8103         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8104         R_EntityMatrix(&rsurface.matrix);
8105         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8106         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8107         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8108         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8109         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8110         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8111         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8112         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8113         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8114         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8115         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8116         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8117         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);
8118         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8119         rsurface.frameblend[0].lerp = 1;
8120         rsurface.ent_alttextures = false;
8121         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8122         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8123         if (wanttangents)
8124         {
8125                 rsurface.modelvertex3f = (float *)vertex3f;
8126                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8127                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8128                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8129         }
8130         else if (wantnormals)
8131         {
8132                 rsurface.modelvertex3f = (float *)vertex3f;
8133                 rsurface.modelsvector3f = NULL;
8134                 rsurface.modeltvector3f = NULL;
8135                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8136         }
8137         else
8138         {
8139                 rsurface.modelvertex3f = (float *)vertex3f;
8140                 rsurface.modelsvector3f = NULL;
8141                 rsurface.modeltvector3f = NULL;
8142                 rsurface.modelnormal3f = NULL;
8143         }
8144         rsurface.modelvertexmesh = NULL;
8145         rsurface.modelvertexmeshbuffer = NULL;
8146         rsurface.modelvertex3fbuffer = NULL;
8147         rsurface.modelvertex3f_vertexbuffer = 0;
8148         rsurface.modelvertex3f_bufferoffset = 0;
8149         rsurface.modelsvector3f_vertexbuffer = 0;
8150         rsurface.modelsvector3f_bufferoffset = 0;
8151         rsurface.modeltvector3f_vertexbuffer = 0;
8152         rsurface.modeltvector3f_bufferoffset = 0;
8153         rsurface.modelnormal3f_vertexbuffer = 0;
8154         rsurface.modelnormal3f_bufferoffset = 0;
8155         rsurface.modelgeneratedvertex = true;
8156         rsurface.modellightmapcolor4f  = (float *)color4f;
8157         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8158         rsurface.modellightmapcolor4f_bufferoffset = 0;
8159         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8160         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8161         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8162         rsurface.modeltexcoordlightmap2f  = NULL;
8163         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8164         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8165         rsurface.modelelement3i = (int *)element3i;
8166         rsurface.modelelement3i_indexbuffer = NULL;
8167         rsurface.modelelement3i_bufferoffset = 0;
8168         rsurface.modelelement3s = (unsigned short *)element3s;
8169         rsurface.modelelement3s_indexbuffer = NULL;
8170         rsurface.modelelement3s_bufferoffset = 0;
8171         rsurface.modellightmapoffsets = NULL;
8172         rsurface.modelsurfaces = NULL;
8173         rsurface.batchgeneratedvertex = false;
8174         rsurface.batchfirstvertex = 0;
8175         rsurface.batchnumvertices = 0;
8176         rsurface.batchfirsttriangle = 0;
8177         rsurface.batchnumtriangles = 0;
8178         rsurface.batchvertex3f  = NULL;
8179         rsurface.batchvertex3f_vertexbuffer = NULL;
8180         rsurface.batchvertex3f_bufferoffset = 0;
8181         rsurface.batchsvector3f = NULL;
8182         rsurface.batchsvector3f_vertexbuffer = NULL;
8183         rsurface.batchsvector3f_bufferoffset = 0;
8184         rsurface.batchtvector3f = NULL;
8185         rsurface.batchtvector3f_vertexbuffer = NULL;
8186         rsurface.batchtvector3f_bufferoffset = 0;
8187         rsurface.batchnormal3f  = NULL;
8188         rsurface.batchnormal3f_vertexbuffer = NULL;
8189         rsurface.batchnormal3f_bufferoffset = 0;
8190         rsurface.batchlightmapcolor4f = NULL;
8191         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8192         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8193         rsurface.batchtexcoordtexture2f = NULL;
8194         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8195         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8196         rsurface.batchtexcoordlightmap2f = NULL;
8197         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8198         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8199         rsurface.batchvertexmesh = NULL;
8200         rsurface.batchvertexmeshbuffer = NULL;
8201         rsurface.batchvertex3fbuffer = NULL;
8202         rsurface.batchelement3i = NULL;
8203         rsurface.batchelement3i_indexbuffer = NULL;
8204         rsurface.batchelement3i_bufferoffset = 0;
8205         rsurface.batchelement3s = NULL;
8206         rsurface.batchelement3s_indexbuffer = NULL;
8207         rsurface.batchelement3s_bufferoffset = 0;
8208         rsurface.passcolor4f = NULL;
8209         rsurface.passcolor4f_vertexbuffer = NULL;
8210         rsurface.passcolor4f_bufferoffset = 0;
8211
8212         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8213         {
8214                 if ((wantnormals || wanttangents) && !normal3f)
8215                 {
8216                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8217                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8218                 }
8219                 if (wanttangents && !svector3f)
8220                 {
8221                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8222                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8223                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8224                 }
8225         }
8226 }
8227
8228 float RSurf_FogPoint(const float *v)
8229 {
8230         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8231         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8232         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8233         float FogHeightFade = r_refdef.fogheightfade;
8234         float fogfrac;
8235         unsigned int fogmasktableindex;
8236         if (r_refdef.fogplaneviewabove)
8237                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8238         else
8239                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8240         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8241         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8242 }
8243
8244 float RSurf_FogVertex(const float *v)
8245 {
8246         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8247         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8248         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8249         float FogHeightFade = rsurface.fogheightfade;
8250         float fogfrac;
8251         unsigned int fogmasktableindex;
8252         if (r_refdef.fogplaneviewabove)
8253                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8254         else
8255                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8256         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8257         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8258 }
8259
8260 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8261 {
8262         int i;
8263         for (i = 0;i < numelements;i++)
8264                 outelement3i[i] = inelement3i[i] + adjust;
8265 }
8266
8267 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8268 extern cvar_t gl_vbo;
8269 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8270 {
8271         int deformindex;
8272         int firsttriangle;
8273         int numtriangles;
8274         int firstvertex;
8275         int endvertex;
8276         int numvertices;
8277         int surfacefirsttriangle;
8278         int surfacenumtriangles;
8279         int surfacefirstvertex;
8280         int surfaceendvertex;
8281         int surfacenumvertices;
8282         int batchnumvertices;
8283         int batchnumtriangles;
8284         int needsupdate;
8285         int i, j;
8286         qboolean gaps;
8287         qboolean dynamicvertex;
8288         float amplitude;
8289         float animpos;
8290         float scale;
8291         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8292         float waveparms[4];
8293         q3shaderinfo_deform_t *deform;
8294         const msurface_t *surface, *firstsurface;
8295         r_vertexmesh_t *vertexmesh;
8296         if (!texturenumsurfaces)
8297                 return;
8298         // find vertex range of this surface batch
8299         gaps = false;
8300         firstsurface = texturesurfacelist[0];
8301         firsttriangle = firstsurface->num_firsttriangle;
8302         batchnumvertices = 0;
8303         batchnumtriangles = 0;
8304         firstvertex = endvertex = firstsurface->num_firstvertex;
8305         for (i = 0;i < texturenumsurfaces;i++)
8306         {
8307                 surface = texturesurfacelist[i];
8308                 if (surface != firstsurface + i)
8309                         gaps = true;
8310                 surfacefirstvertex = surface->num_firstvertex;
8311                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8312                 surfacenumvertices = surface->num_vertices;
8313                 surfacenumtriangles = surface->num_triangles;
8314                 if (firstvertex > surfacefirstvertex)
8315                         firstvertex = surfacefirstvertex;
8316                 if (endvertex < surfaceendvertex)
8317                         endvertex = surfaceendvertex;
8318                 batchnumvertices += surfacenumvertices;
8319                 batchnumtriangles += surfacenumtriangles;
8320         }
8321
8322         // we now know the vertex range used, and if there are any gaps in it
8323         rsurface.batchfirstvertex = firstvertex;
8324         rsurface.batchnumvertices = endvertex - firstvertex;
8325         rsurface.batchfirsttriangle = firsttriangle;
8326         rsurface.batchnumtriangles = batchnumtriangles;
8327
8328         // this variable holds flags for which properties have been updated that
8329         // may require regenerating vertexmesh array...
8330         needsupdate = 0;
8331
8332         // check if any dynamic vertex processing must occur
8333         dynamicvertex = false;
8334
8335         // if there is a chance of animated vertex colors, it's a dynamic batch
8336         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8337         {
8338                 dynamicvertex = true;
8339                 batchneed |= BATCHNEED_NOGAPS;
8340                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8341         }
8342
8343         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8344         {
8345                 switch (deform->deform)
8346                 {
8347                 default:
8348                 case Q3DEFORM_PROJECTIONSHADOW:
8349                 case Q3DEFORM_TEXT0:
8350                 case Q3DEFORM_TEXT1:
8351                 case Q3DEFORM_TEXT2:
8352                 case Q3DEFORM_TEXT3:
8353                 case Q3DEFORM_TEXT4:
8354                 case Q3DEFORM_TEXT5:
8355                 case Q3DEFORM_TEXT6:
8356                 case Q3DEFORM_TEXT7:
8357                 case Q3DEFORM_NONE:
8358                         break;
8359                 case Q3DEFORM_AUTOSPRITE:
8360                         dynamicvertex = true;
8361                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8362                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8363                         break;
8364                 case Q3DEFORM_AUTOSPRITE2:
8365                         dynamicvertex = true;
8366                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8367                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8368                         break;
8369                 case Q3DEFORM_NORMAL:
8370                         dynamicvertex = true;
8371                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8372                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8373                         break;
8374                 case Q3DEFORM_WAVE:
8375                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8376                                 break; // if wavefunc is a nop, ignore this transform
8377                         dynamicvertex = true;
8378                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8379                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8380                         break;
8381                 case Q3DEFORM_BULGE:
8382                         dynamicvertex = true;
8383                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8384                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8385                         break;
8386                 case Q3DEFORM_MOVE:
8387                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8388                                 break; // if wavefunc is a nop, ignore this transform
8389                         dynamicvertex = true;
8390                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8391                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8392                         break;
8393                 }
8394         }
8395         switch(rsurface.texture->tcgen.tcgen)
8396         {
8397         default:
8398         case Q3TCGEN_TEXTURE:
8399                 break;
8400         case Q3TCGEN_LIGHTMAP:
8401                 dynamicvertex = true;
8402                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8403                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8404                 break;
8405         case Q3TCGEN_VECTOR:
8406                 dynamicvertex = true;
8407                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8408                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8409                 break;
8410         case Q3TCGEN_ENVIRONMENT:
8411                 dynamicvertex = true;
8412                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8413                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8414                 break;
8415         }
8416         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8417         {
8418                 dynamicvertex = true;
8419                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8420                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8421         }
8422
8423         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8424         {
8425                 dynamicvertex = true;
8426                 batchneed |= BATCHNEED_NOGAPS;
8427                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8428         }
8429
8430         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8431         {
8432                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8433                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8434                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8435                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8436                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8437                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8438                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8439         }
8440
8441         // when the model data has no vertex buffer (dynamic mesh), we need to
8442         // eliminate gaps
8443         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8444                 batchneed |= BATCHNEED_NOGAPS;
8445
8446         // if needsupdate, we have to do a dynamic vertex batch for sure
8447         if (needsupdate & batchneed)
8448                 dynamicvertex = true;
8449
8450         // see if we need to build vertexmesh from arrays
8451         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8452                 dynamicvertex = true;
8453
8454         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8455         // also some drivers strongly dislike firstvertex
8456         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8457                 dynamicvertex = true;
8458
8459         rsurface.batchvertex3f = rsurface.modelvertex3f;
8460         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8461         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8462         rsurface.batchsvector3f = rsurface.modelsvector3f;
8463         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8464         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8465         rsurface.batchtvector3f = rsurface.modeltvector3f;
8466         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8467         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8468         rsurface.batchnormal3f = rsurface.modelnormal3f;
8469         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8470         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8471         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8472         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8473         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8474         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8475         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8476         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8477         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8478         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8479         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8480         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8481         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8482         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8483         rsurface.batchelement3i = rsurface.modelelement3i;
8484         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8485         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8486         rsurface.batchelement3s = rsurface.modelelement3s;
8487         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8488         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8489
8490         // if any dynamic vertex processing has to occur in software, we copy the
8491         // entire surface list together before processing to rebase the vertices
8492         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8493         //
8494         // if any gaps exist and we do not have a static vertex buffer, we have to
8495         // copy the surface list together to avoid wasting upload bandwidth on the
8496         // vertices in the gaps.
8497         //
8498         // if gaps exist and we have a static vertex buffer, we still have to
8499         // combine the index buffer ranges into one dynamic index buffer.
8500         //
8501         // in all cases we end up with data that can be drawn in one call.
8502
8503         if (!dynamicvertex)
8504         {
8505                 // static vertex data, just set pointers...
8506                 rsurface.batchgeneratedvertex = false;
8507                 // if there are gaps, we want to build a combined index buffer,
8508                 // otherwise use the original static buffer with an appropriate offset
8509                 if (gaps)
8510                 {
8511                         // build a new triangle elements array for this batch
8512                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8513                         rsurface.batchfirsttriangle = 0;
8514                         numtriangles = 0;
8515                         for (i = 0;i < texturenumsurfaces;i++)
8516                         {
8517                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8518                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8519                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8520                                 numtriangles += surfacenumtriangles;
8521                         }
8522                         rsurface.batchelement3i_indexbuffer = NULL;
8523                         rsurface.batchelement3i_bufferoffset = 0;
8524                         rsurface.batchelement3s = NULL;
8525                         rsurface.batchelement3s_indexbuffer = NULL;
8526                         rsurface.batchelement3s_bufferoffset = 0;
8527                         if (endvertex <= 65536)
8528                         {
8529                                 // make a 16bit (unsigned short) index array if possible
8530                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8531                                 for (i = 0;i < numtriangles*3;i++)
8532                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8533                         }
8534                 }
8535                 return;
8536         }
8537
8538         // something needs software processing, do it for real...
8539         // we only directly handle separate array data in this case and then
8540         // generate interleaved data if needed...
8541         rsurface.batchgeneratedvertex = true;
8542
8543         // now copy the vertex data into a combined array and make an index array
8544         // (this is what Quake3 does all the time)
8545         //if (gaps || rsurface.batchfirstvertex)
8546         {
8547                 rsurface.batchvertex3fbuffer = NULL;
8548                 rsurface.batchvertexmesh = NULL;
8549                 rsurface.batchvertexmeshbuffer = NULL;
8550                 rsurface.batchvertex3f = NULL;
8551                 rsurface.batchvertex3f_vertexbuffer = NULL;
8552                 rsurface.batchvertex3f_bufferoffset = 0;
8553                 rsurface.batchsvector3f = NULL;
8554                 rsurface.batchsvector3f_vertexbuffer = NULL;
8555                 rsurface.batchsvector3f_bufferoffset = 0;
8556                 rsurface.batchtvector3f = NULL;
8557                 rsurface.batchtvector3f_vertexbuffer = NULL;
8558                 rsurface.batchtvector3f_bufferoffset = 0;
8559                 rsurface.batchnormal3f = NULL;
8560                 rsurface.batchnormal3f_vertexbuffer = NULL;
8561                 rsurface.batchnormal3f_bufferoffset = 0;
8562                 rsurface.batchlightmapcolor4f = NULL;
8563                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8564                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8565                 rsurface.batchtexcoordtexture2f = NULL;
8566                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8567                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8568                 rsurface.batchtexcoordlightmap2f = NULL;
8569                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8570                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8571                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8572                 rsurface.batchelement3i_indexbuffer = NULL;
8573                 rsurface.batchelement3i_bufferoffset = 0;
8574                 rsurface.batchelement3s = NULL;
8575                 rsurface.batchelement3s_indexbuffer = NULL;
8576                 rsurface.batchelement3s_bufferoffset = 0;
8577                 // we'll only be setting up certain arrays as needed
8578                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8579                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8580                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8581                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8582                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8583                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8584                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8585                 {
8586                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8587                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8588                 }
8589                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8590                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8591                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8592                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8593                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8594                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8595                 numvertices = 0;
8596                 numtriangles = 0;
8597                 for (i = 0;i < texturenumsurfaces;i++)
8598                 {
8599                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8600                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8601                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8602                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8603                         // copy only the data requested
8604                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8605                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8606                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8607                         {
8608                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8609                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8610                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8611                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8612                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8613                                 {
8614                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8615                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8616                                 }
8617                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8618                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8619                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8620                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8621                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8622                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8623                         }
8624                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8625                         numvertices += surfacenumvertices;
8626                         numtriangles += surfacenumtriangles;
8627                 }
8628
8629                 // generate a 16bit index array as well if possible
8630                 // (in general, dynamic batches fit)
8631                 if (numvertices <= 65536)
8632                 {
8633                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8634                         for (i = 0;i < numtriangles*3;i++)
8635                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8636                 }
8637
8638                 // since we've copied everything, the batch now starts at 0
8639                 rsurface.batchfirstvertex = 0;
8640                 rsurface.batchnumvertices = batchnumvertices;
8641                 rsurface.batchfirsttriangle = 0;
8642                 rsurface.batchnumtriangles = batchnumtriangles;
8643         }
8644
8645         // q1bsp surfaces rendered in vertex color mode have to have colors
8646         // calculated based on lightstyles
8647         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8648         {
8649                 // generate color arrays for the surfaces in this list
8650                 int c[4];
8651                 int scale;
8652                 int size3;
8653                 const int *offsets;
8654                 const unsigned char *lm;
8655                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8656                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8657                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8658                 numvertices = 0;
8659                 for (i = 0;i < texturenumsurfaces;i++)
8660                 {
8661                         surface = texturesurfacelist[i];
8662                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8663                         surfacenumvertices = surface->num_vertices;
8664                         if (surface->lightmapinfo->samples)
8665                         {
8666                                 for (j = 0;j < surfacenumvertices;j++)
8667                                 {
8668                                         lm = surface->lightmapinfo->samples + offsets[j];
8669                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8670                                         VectorScale(lm, scale, c);
8671                                         if (surface->lightmapinfo->styles[1] != 255)
8672                                         {
8673                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8674                                                 lm += size3;
8675                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8676                                                 VectorMA(c, scale, lm, c);
8677                                                 if (surface->lightmapinfo->styles[2] != 255)
8678                                                 {
8679                                                         lm += size3;
8680                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8681                                                         VectorMA(c, scale, lm, c);
8682                                                         if (surface->lightmapinfo->styles[3] != 255)
8683                                                         {
8684                                                                 lm += size3;
8685                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8686                                                                 VectorMA(c, scale, lm, c);
8687                                                         }
8688                                                 }
8689                                         }
8690                                         c[0] >>= 7;
8691                                         c[1] >>= 7;
8692                                         c[2] >>= 7;
8693                                         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);
8694                                         numvertices++;
8695                                 }
8696                         }
8697                         else
8698                         {
8699                                 for (j = 0;j < surfacenumvertices;j++)
8700                                 {
8701                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8702                                         numvertices++;
8703                                 }
8704                         }
8705                 }
8706         }
8707
8708         // if vertices are deformed (sprite flares and things in maps, possibly
8709         // water waves, bulges and other deformations), modify the copied vertices
8710         // in place
8711         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8712         {
8713                 switch (deform->deform)
8714                 {
8715                 default:
8716                 case Q3DEFORM_PROJECTIONSHADOW:
8717                 case Q3DEFORM_TEXT0:
8718                 case Q3DEFORM_TEXT1:
8719                 case Q3DEFORM_TEXT2:
8720                 case Q3DEFORM_TEXT3:
8721                 case Q3DEFORM_TEXT4:
8722                 case Q3DEFORM_TEXT5:
8723                 case Q3DEFORM_TEXT6:
8724                 case Q3DEFORM_TEXT7:
8725                 case Q3DEFORM_NONE:
8726                         break;
8727                 case Q3DEFORM_AUTOSPRITE:
8728                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8729                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8730                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8731                         VectorNormalize(newforward);
8732                         VectorNormalize(newright);
8733                         VectorNormalize(newup);
8734 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8735 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8736 //                      rsurface.batchvertex3f_bufferoffset = 0;
8737 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8738 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8739 //                      rsurface.batchsvector3f_bufferoffset = 0;
8740 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8741 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8742 //                      rsurface.batchtvector3f_bufferoffset = 0;
8743 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8744 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8745 //                      rsurface.batchnormal3f_bufferoffset = 0;
8746                         // a single autosprite surface can contain multiple sprites...
8747                         for (j = 0;j < batchnumvertices - 3;j += 4)
8748                         {
8749                                 VectorClear(center);
8750                                 for (i = 0;i < 4;i++)
8751                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8752                                 VectorScale(center, 0.25f, center);
8753                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8754                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8755                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8756                                 for (i = 0;i < 4;i++)
8757                                 {
8758                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8759                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8760                                 }
8761                         }
8762                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8763                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8764                         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);
8765                         break;
8766                 case Q3DEFORM_AUTOSPRITE2:
8767                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8768                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8769                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8770                         VectorNormalize(newforward);
8771                         VectorNormalize(newright);
8772                         VectorNormalize(newup);
8773 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8774 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8775 //                      rsurface.batchvertex3f_bufferoffset = 0;
8776                         {
8777                                 const float *v1, *v2;
8778                                 vec3_t start, end;
8779                                 float f, l;
8780                                 struct
8781                                 {
8782                                         float length2;
8783                                         const float *v1;
8784                                         const float *v2;
8785                                 }
8786                                 shortest[2];
8787                                 memset(shortest, 0, sizeof(shortest));
8788                                 // a single autosprite surface can contain multiple sprites...
8789                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8790                                 {
8791                                         VectorClear(center);
8792                                         for (i = 0;i < 4;i++)
8793                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8794                                         VectorScale(center, 0.25f, center);
8795                                         // find the two shortest edges, then use them to define the
8796                                         // axis vectors for rotating around the central axis
8797                                         for (i = 0;i < 6;i++)
8798                                         {
8799                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8800                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8801                                                 l = VectorDistance2(v1, v2);
8802                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8803                                                 if (v1[2] != v2[2])
8804                                                         l += (1.0f / 1024.0f);
8805                                                 if (shortest[0].length2 > l || i == 0)
8806                                                 {
8807                                                         shortest[1] = shortest[0];
8808                                                         shortest[0].length2 = l;
8809                                                         shortest[0].v1 = v1;
8810                                                         shortest[0].v2 = v2;
8811                                                 }
8812                                                 else if (shortest[1].length2 > l || i == 1)
8813                                                 {
8814                                                         shortest[1].length2 = l;
8815                                                         shortest[1].v1 = v1;
8816                                                         shortest[1].v2 = v2;
8817                                                 }
8818                                         }
8819                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8820                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8821                                         // this calculates the right vector from the shortest edge
8822                                         // and the up vector from the edge midpoints
8823                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8824                                         VectorNormalize(right);
8825                                         VectorSubtract(end, start, up);
8826                                         VectorNormalize(up);
8827                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8828                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8829                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8830                                         VectorNegate(forward, forward);
8831                                         VectorReflect(forward, 0, up, forward);
8832                                         VectorNormalize(forward);
8833                                         CrossProduct(up, forward, newright);
8834                                         VectorNormalize(newright);
8835                                         // rotate the quad around the up axis vector, this is made
8836                                         // especially easy by the fact we know the quad is flat,
8837                                         // so we only have to subtract the center position and
8838                                         // measure distance along the right vector, and then
8839                                         // multiply that by the newright vector and add back the
8840                                         // center position
8841                                         // we also need to subtract the old position to undo the
8842                                         // displacement from the center, which we do with a
8843                                         // DotProduct, the subtraction/addition of center is also
8844                                         // optimized into DotProducts here
8845                                         l = DotProduct(right, center);
8846                                         for (i = 0;i < 4;i++)
8847                                         {
8848                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8849                                                 f = DotProduct(right, v1) - l;
8850                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8851                                         }
8852                                 }
8853                         }
8854                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8855                         {
8856 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8857 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8858 //                              rsurface.batchnormal3f_bufferoffset = 0;
8859                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8860                         }
8861                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8862                         {
8863 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8864 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8865 //                              rsurface.batchsvector3f_bufferoffset = 0;
8866 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8867 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8868 //                              rsurface.batchtvector3f_bufferoffset = 0;
8869                                 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);
8870                         }
8871                         break;
8872                 case Q3DEFORM_NORMAL:
8873                         // deform the normals to make reflections wavey
8874                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8875                         rsurface.batchnormal3f_vertexbuffer = NULL;
8876                         rsurface.batchnormal3f_bufferoffset = 0;
8877                         for (j = 0;j < batchnumvertices;j++)
8878                         {
8879                                 float vertex[3];
8880                                 float *normal = rsurface.batchnormal3f + 3*j;
8881                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8882                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8883                                 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]);
8884                                 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]);
8885                                 VectorNormalize(normal);
8886                         }
8887                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8888                         {
8889 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8890 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8891 //                              rsurface.batchsvector3f_bufferoffset = 0;
8892 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8893 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8894 //                              rsurface.batchtvector3f_bufferoffset = 0;
8895                                 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);
8896                         }
8897                         break;
8898                 case Q3DEFORM_WAVE:
8899                         // deform vertex array to make wavey water and flags and such
8900                         waveparms[0] = deform->waveparms[0];
8901                         waveparms[1] = deform->waveparms[1];
8902                         waveparms[2] = deform->waveparms[2];
8903                         waveparms[3] = deform->waveparms[3];
8904                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8905                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8906                         // this is how a divisor of vertex influence on deformation
8907                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8908                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8909 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8910 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8911 //                      rsurface.batchvertex3f_bufferoffset = 0;
8912 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8913 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8914 //                      rsurface.batchnormal3f_bufferoffset = 0;
8915                         for (j = 0;j < batchnumvertices;j++)
8916                         {
8917                                 // if the wavefunc depends on time, evaluate it per-vertex
8918                                 if (waveparms[3])
8919                                 {
8920                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8921                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8922                                 }
8923                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8924                         }
8925                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8926                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8927                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8928                         {
8929 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8930 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8931 //                              rsurface.batchsvector3f_bufferoffset = 0;
8932 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8933 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8934 //                              rsurface.batchtvector3f_bufferoffset = 0;
8935                                 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);
8936                         }
8937                         break;
8938                 case Q3DEFORM_BULGE:
8939                         // deform vertex array to make the surface have moving bulges
8940 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8941 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8942 //                      rsurface.batchvertex3f_bufferoffset = 0;
8943 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8944 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8945 //                      rsurface.batchnormal3f_bufferoffset = 0;
8946                         for (j = 0;j < batchnumvertices;j++)
8947                         {
8948                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8949                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8950                         }
8951                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8952                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8953                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8954                         {
8955 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8956 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8957 //                              rsurface.batchsvector3f_bufferoffset = 0;
8958 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8959 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8960 //                              rsurface.batchtvector3f_bufferoffset = 0;
8961                                 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);
8962                         }
8963                         break;
8964                 case Q3DEFORM_MOVE:
8965                         // deform vertex array
8966                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8967                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8968                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8969                         VectorScale(deform->parms, scale, waveparms);
8970 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8971 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8972 //                      rsurface.batchvertex3f_bufferoffset = 0;
8973                         for (j = 0;j < batchnumvertices;j++)
8974                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8975                         break;
8976                 }
8977         }
8978
8979         // generate texcoords based on the chosen texcoord source
8980         switch(rsurface.texture->tcgen.tcgen)
8981         {
8982         default:
8983         case Q3TCGEN_TEXTURE:
8984                 break;
8985         case Q3TCGEN_LIGHTMAP:
8986 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8987 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8988 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8989                 if (rsurface.batchtexcoordlightmap2f)
8990                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8991                 break;
8992         case Q3TCGEN_VECTOR:
8993 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8994 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8995 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8996                 for (j = 0;j < batchnumvertices;j++)
8997                 {
8998                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8999                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9000                 }
9001                 break;
9002         case Q3TCGEN_ENVIRONMENT:
9003                 // make environment reflections using a spheremap
9004                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9005                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9006                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9007                 for (j = 0;j < batchnumvertices;j++)
9008                 {
9009                         // identical to Q3A's method, but executed in worldspace so
9010                         // carried models can be shiny too
9011
9012                         float viewer[3], d, reflected[3], worldreflected[3];
9013
9014                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9015                         // VectorNormalize(viewer);
9016
9017                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9018
9019                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9020                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9021                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9022                         // note: this is proportinal to viewer, so we can normalize later
9023
9024                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9025                         VectorNormalize(worldreflected);
9026
9027                         // note: this sphere map only uses world x and z!
9028                         // so positive and negative y will LOOK THE SAME.
9029                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9030                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9031                 }
9032                 break;
9033         }
9034         // the only tcmod that needs software vertex processing is turbulent, so
9035         // check for it here and apply the changes if needed
9036         // and we only support that as the first one
9037         // (handling a mixture of turbulent and other tcmods would be problematic
9038         //  without punting it entirely to a software path)
9039         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9040         {
9041                 amplitude = rsurface.texture->tcmods[0].parms[1];
9042                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9043 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9044 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9045 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9046                 for (j = 0;j < batchnumvertices;j++)
9047                 {
9048                         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);
9049                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9050                 }
9051         }
9052
9053         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9054         {
9055                 // convert the modified arrays to vertex structs
9056 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9057 //              rsurface.batchvertexmeshbuffer = NULL;
9058                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9059                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9060                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9061                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9062                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9063                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9064                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9065                 {
9066                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9067                         {
9068                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9069                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9070                         }
9071                 }
9072                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9073                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9074                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9075                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9076                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9077                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9078                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9079                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9080                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9081         }
9082 }
9083
9084 void RSurf_DrawBatch(void)
9085 {
9086         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9087         // through the pipeline, killing it earlier in the pipeline would have
9088         // per-surface overhead rather than per-batch overhead, so it's best to
9089         // reject it here, before it hits glDraw.
9090         if (rsurface.batchnumtriangles == 0)
9091                 return;
9092 #if 0
9093         // batch debugging code
9094         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9095         {
9096                 int i;
9097                 int j;
9098                 int c;
9099                 const int *e;
9100                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9101                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9102                 {
9103                         c = e[i];
9104                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9105                         {
9106                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9107                                 {
9108                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9109                                                 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);
9110                                         break;
9111                                 }
9112                         }
9113                 }
9114         }
9115 #endif
9116         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);
9117 }
9118
9119 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9120 {
9121         // pick the closest matching water plane
9122         int planeindex, vertexindex, bestplaneindex = -1;
9123         float d, bestd;
9124         vec3_t vert;
9125         const float *v;
9126         r_waterstate_waterplane_t *p;
9127         qboolean prepared = false;
9128         bestd = 0;
9129         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9130         {
9131                 if(p->camera_entity != rsurface.texture->camera_entity)
9132                         continue;
9133                 d = 0;
9134                 if(!prepared)
9135                 {
9136                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9137                         prepared = true;
9138                         if(rsurface.batchnumvertices == 0)
9139                                 break;
9140                 }
9141                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9142                 {
9143                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9144                         d += fabs(PlaneDiff(vert, &p->plane));
9145                 }
9146                 if (bestd > d || bestplaneindex < 0)
9147                 {
9148                         bestd = d;
9149                         bestplaneindex = planeindex;
9150                 }
9151         }
9152         return bestplaneindex;
9153         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9154         // this situation though, as it might be better to render single larger
9155         // batches with useless stuff (backface culled for example) than to
9156         // render multiple smaller batches
9157 }
9158
9159 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9160 {
9161         int i;
9162         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9163         rsurface.passcolor4f_vertexbuffer = 0;
9164         rsurface.passcolor4f_bufferoffset = 0;
9165         for (i = 0;i < rsurface.batchnumvertices;i++)
9166                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9167 }
9168
9169 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9170 {
9171         int i;
9172         float f;
9173         const float *v;
9174         const float *c;
9175         float *c2;
9176         if (rsurface.passcolor4f)
9177         {
9178                 // generate color arrays
9179                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9180                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9181                 rsurface.passcolor4f_vertexbuffer = 0;
9182                 rsurface.passcolor4f_bufferoffset = 0;
9183                 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)
9184                 {
9185                         f = RSurf_FogVertex(v);
9186                         c2[0] = c[0] * f;
9187                         c2[1] = c[1] * f;
9188                         c2[2] = c[2] * f;
9189                         c2[3] = c[3];
9190                 }
9191         }
9192         else
9193         {
9194                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9195                 rsurface.passcolor4f_vertexbuffer = 0;
9196                 rsurface.passcolor4f_bufferoffset = 0;
9197                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9198                 {
9199                         f = RSurf_FogVertex(v);
9200                         c2[0] = f;
9201                         c2[1] = f;
9202                         c2[2] = f;
9203                         c2[3] = 1;
9204                 }
9205         }
9206 }
9207
9208 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9209 {
9210         int i;
9211         float f;
9212         const float *v;
9213         const float *c;
9214         float *c2;
9215         if (!rsurface.passcolor4f)
9216                 return;
9217         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9218         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9219         rsurface.passcolor4f_vertexbuffer = 0;
9220         rsurface.passcolor4f_bufferoffset = 0;
9221         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)
9222         {
9223                 f = RSurf_FogVertex(v);
9224                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9225                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9226                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9227                 c2[3] = c[3];
9228         }
9229 }
9230
9231 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9232 {
9233         int i;
9234         const float *c;
9235         float *c2;
9236         if (!rsurface.passcolor4f)
9237                 return;
9238         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9239         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9240         rsurface.passcolor4f_vertexbuffer = 0;
9241         rsurface.passcolor4f_bufferoffset = 0;
9242         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9243         {
9244                 c2[0] = c[0] * r;
9245                 c2[1] = c[1] * g;
9246                 c2[2] = c[2] * b;
9247                 c2[3] = c[3] * a;
9248         }
9249 }
9250
9251 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9252 {
9253         int i;
9254         const float *c;
9255         float *c2;
9256         if (!rsurface.passcolor4f)
9257                 return;
9258         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9259         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9260         rsurface.passcolor4f_vertexbuffer = 0;
9261         rsurface.passcolor4f_bufferoffset = 0;
9262         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9263         {
9264                 c2[0] = c[0] + r_refdef.scene.ambient;
9265                 c2[1] = c[1] + r_refdef.scene.ambient;
9266                 c2[2] = c[2] + r_refdef.scene.ambient;
9267                 c2[3] = c[3];
9268         }
9269 }
9270
9271 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9272 {
9273         // TODO: optimize
9274         rsurface.passcolor4f = NULL;
9275         rsurface.passcolor4f_vertexbuffer = 0;
9276         rsurface.passcolor4f_bufferoffset = 0;
9277         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9278         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9279         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9280         GL_Color(r, g, b, a);
9281         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9282         RSurf_DrawBatch();
9283 }
9284
9285 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9286 {
9287         // TODO: optimize applyfog && applycolor case
9288         // just apply fog if necessary, and tint the fog color array if necessary
9289         rsurface.passcolor4f = NULL;
9290         rsurface.passcolor4f_vertexbuffer = 0;
9291         rsurface.passcolor4f_bufferoffset = 0;
9292         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9293         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9294         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9295         GL_Color(r, g, b, a);
9296         RSurf_DrawBatch();
9297 }
9298
9299 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9300 {
9301         // TODO: optimize
9302         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9303         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9304         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9305         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9306         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9307         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9308         GL_Color(r, g, b, a);
9309         RSurf_DrawBatch();
9310 }
9311
9312 static void RSurf_DrawBatch_GL11_ClampColor(void)
9313 {
9314         int i;
9315         const float *c1;
9316         float *c2;
9317         if (!rsurface.passcolor4f)
9318                 return;
9319         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9320         {
9321                 c2[0] = bound(0.0f, c1[0], 1.0f);
9322                 c2[1] = bound(0.0f, c1[1], 1.0f);
9323                 c2[2] = bound(0.0f, c1[2], 1.0f);
9324                 c2[3] = bound(0.0f, c1[3], 1.0f);
9325         }
9326 }
9327
9328 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9329 {
9330         int i;
9331         float f;
9332         const float *v;
9333         const float *n;
9334         float *c;
9335         //vec3_t eyedir;
9336
9337         // fake shading
9338         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339         rsurface.passcolor4f_vertexbuffer = 0;
9340         rsurface.passcolor4f_bufferoffset = 0;
9341         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)
9342         {
9343                 f = -DotProduct(r_refdef.view.forward, n);
9344                 f = max(0, f);
9345                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9346                 f *= r_refdef.lightmapintensity;
9347                 Vector4Set(c, f, f, f, 1);
9348         }
9349 }
9350
9351 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9352 {
9353         RSurf_DrawBatch_GL11_ApplyFakeLight();
9354         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9355         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9356         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9357         GL_Color(r, g, b, a);
9358         RSurf_DrawBatch();
9359 }
9360
9361 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9362 {
9363         int i;
9364         float f;
9365         float alpha;
9366         const float *v;
9367         const float *n;
9368         float *c;
9369         vec3_t ambientcolor;
9370         vec3_t diffusecolor;
9371         vec3_t lightdir;
9372         // TODO: optimize
9373         // model lighting
9374         VectorCopy(rsurface.modellight_lightdir, lightdir);
9375         f = 0.5f * r_refdef.lightmapintensity;
9376         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9377         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9378         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9379         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9380         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9381         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9382         alpha = *a;
9383         if (VectorLength2(diffusecolor) > 0)
9384         {
9385                 // q3-style directional shading
9386                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9387                 rsurface.passcolor4f_vertexbuffer = 0;
9388                 rsurface.passcolor4f_bufferoffset = 0;
9389                 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)
9390                 {
9391                         if ((f = DotProduct(n, lightdir)) > 0)
9392                                 VectorMA(ambientcolor, f, diffusecolor, c);
9393                         else
9394                                 VectorCopy(ambientcolor, c);
9395                         c[3] = alpha;
9396                 }
9397                 *r = 1;
9398                 *g = 1;
9399                 *b = 1;
9400                 *a = 1;
9401                 *applycolor = false;
9402         }
9403         else
9404         {
9405                 *r = ambientcolor[0];
9406                 *g = ambientcolor[1];
9407                 *b = ambientcolor[2];
9408                 rsurface.passcolor4f = NULL;
9409                 rsurface.passcolor4f_vertexbuffer = 0;
9410                 rsurface.passcolor4f_bufferoffset = 0;
9411         }
9412 }
9413
9414 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9415 {
9416         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9417         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9418         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9419         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9420         GL_Color(r, g, b, a);
9421         RSurf_DrawBatch();
9422 }
9423
9424 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9425 {
9426         int i;
9427         float f;
9428         const float *v;
9429         float *c;
9430
9431         // fake shading
9432         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9433         rsurface.passcolor4f_vertexbuffer = 0;
9434         rsurface.passcolor4f_bufferoffset = 0;
9435
9436         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9437         {
9438                 f = 1 - RSurf_FogVertex(v);
9439                 c[0] = r;
9440                 c[1] = g;
9441                 c[2] = b;
9442                 c[3] = f * a;
9443         }
9444 }
9445
9446 void RSurf_SetupDepthAndCulling(void)
9447 {
9448         // submodels are biased to avoid z-fighting with world surfaces that they
9449         // may be exactly overlapping (avoids z-fighting artifacts on certain
9450         // doors and things in Quake maps)
9451         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9452         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9453         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9454         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9455 }
9456
9457 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9458 {
9459         // transparent sky would be ridiculous
9460         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9461                 return;
9462         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9463         skyrenderlater = true;
9464         RSurf_SetupDepthAndCulling();
9465         GL_DepthMask(true);
9466         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9467         // skymasking on them, and Quake3 never did sky masking (unlike
9468         // software Quake and software Quake2), so disable the sky masking
9469         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9470         // and skymasking also looks very bad when noclipping outside the
9471         // level, so don't use it then either.
9472         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9473         {
9474                 R_Mesh_ResetTextureState();
9475                 if (skyrendermasked)
9476                 {
9477                         R_SetupShader_DepthOrShadow();
9478                         // depth-only (masking)
9479                         GL_ColorMask(0,0,0,0);
9480                         // just to make sure that braindead drivers don't draw
9481                         // anything despite that colormask...
9482                         GL_BlendFunc(GL_ZERO, GL_ONE);
9483                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9484                         if (rsurface.batchvertex3fbuffer)
9485                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9486                         else
9487                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9488                 }
9489                 else
9490                 {
9491                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9492                         // fog sky
9493                         GL_BlendFunc(GL_ONE, GL_ZERO);
9494                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9495                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9496                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9497                 }
9498                 RSurf_DrawBatch();
9499                 if (skyrendermasked)
9500                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9501         }
9502         R_Mesh_ResetTextureState();
9503         GL_Color(1, 1, 1, 1);
9504 }
9505
9506 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9507 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9508 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9509 {
9510         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9511                 return;
9512         if (prepass)
9513         {
9514                 // render screenspace normalmap to texture
9515                 GL_DepthMask(true);
9516                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9517                 RSurf_DrawBatch();
9518         }
9519
9520         // bind lightmap texture
9521
9522         // water/refraction/reflection/camera surfaces have to be handled specially
9523         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9524         {
9525                 int start, end, startplaneindex;
9526                 for (start = 0;start < texturenumsurfaces;start = end)
9527                 {
9528                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9529                         if(startplaneindex < 0)
9530                         {
9531                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9532                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9533                                 end = start + 1;
9534                                 continue;
9535                         }
9536                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9537                                 ;
9538                         // now that we have a batch using the same planeindex, render it
9539                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9540                         {
9541                                 // render water or distortion background
9542                                 GL_DepthMask(true);
9543                                 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));
9544                                 RSurf_DrawBatch();
9545                                 // blend surface on top
9546                                 GL_DepthMask(false);
9547                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9548                                 RSurf_DrawBatch();
9549                         }
9550                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9551                         {
9552                                 // render surface with reflection texture as input
9553                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9554                                 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));
9555                                 RSurf_DrawBatch();
9556                         }
9557                 }
9558                 return;
9559         }
9560
9561         // render surface batch normally
9562         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9563         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9564         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9565                 GL_AlphaTest(true);
9566         RSurf_DrawBatch();
9567         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9568                 GL_AlphaTest(false);
9569 }
9570
9571 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9572 {
9573         // OpenGL 1.3 path - anything not completely ancient
9574         qboolean applycolor;
9575         qboolean applyfog;
9576         int layerindex;
9577         const texturelayer_t *layer;
9578         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);
9579         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9580
9581         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9582         {
9583                 vec4_t layercolor;
9584                 int layertexrgbscale;
9585                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9586                 {
9587                         if (layerindex == 0)
9588                                 GL_AlphaTest(true);
9589                         else
9590                         {
9591                                 GL_AlphaTest(false);
9592                                 GL_DepthFunc(GL_EQUAL);
9593                         }
9594                 }
9595                 GL_DepthMask(layer->depthmask && writedepth);
9596                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9597                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9598                 {
9599                         layertexrgbscale = 4;
9600                         VectorScale(layer->color, 0.25f, layercolor);
9601                 }
9602                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9603                 {
9604                         layertexrgbscale = 2;
9605                         VectorScale(layer->color, 0.5f, layercolor);
9606                 }
9607                 else
9608                 {
9609                         layertexrgbscale = 1;
9610                         VectorScale(layer->color, 1.0f, layercolor);
9611                 }
9612                 layercolor[3] = layer->color[3];
9613                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9614                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9615                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9616                 switch (layer->type)
9617                 {
9618                 case TEXTURELAYERTYPE_LITTEXTURE:
9619                         // single-pass lightmapped texture with 2x rgbscale
9620                         R_Mesh_TexBind(0, r_texture_white);
9621                         R_Mesh_TexMatrix(0, NULL);
9622                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9623                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9624                         R_Mesh_TexBind(1, layer->texture);
9625                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9626                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9627                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9628                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9629                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9630                         else if (FAKELIGHT_ENABLED)
9631                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9632                         else if (rsurface.uselightmaptexture)
9633                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9634                         else
9635                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9636                         break;
9637                 case TEXTURELAYERTYPE_TEXTURE:
9638                         // singletexture unlit texture with transparency support
9639                         R_Mesh_TexBind(0, layer->texture);
9640                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9641                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9642                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9643                         R_Mesh_TexBind(1, 0);
9644                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9645                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9646                         break;
9647                 case TEXTURELAYERTYPE_FOG:
9648                         // singletexture fogging
9649                         if (layer->texture)
9650                         {
9651                                 R_Mesh_TexBind(0, layer->texture);
9652                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9653                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9654                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9655                         }
9656                         else
9657                         {
9658                                 R_Mesh_TexBind(0, 0);
9659                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9660                         }
9661                         R_Mesh_TexBind(1, 0);
9662                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9663                         // generate a color array for the fog pass
9664                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9665                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9666                         RSurf_DrawBatch();
9667                         break;
9668                 default:
9669                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9670                 }
9671         }
9672         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9673         {
9674                 GL_DepthFunc(GL_LEQUAL);
9675                 GL_AlphaTest(false);
9676         }
9677 }
9678
9679 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9680 {
9681         // OpenGL 1.1 - crusty old voodoo path
9682         qboolean applyfog;
9683         int layerindex;
9684         const texturelayer_t *layer;
9685         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);
9686         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9687
9688         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9689         {
9690                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9691                 {
9692                         if (layerindex == 0)
9693                                 GL_AlphaTest(true);
9694                         else
9695                         {
9696                                 GL_AlphaTest(false);
9697                                 GL_DepthFunc(GL_EQUAL);
9698                         }
9699                 }
9700                 GL_DepthMask(layer->depthmask && writedepth);
9701                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9702                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9703                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9704                 switch (layer->type)
9705                 {
9706                 case TEXTURELAYERTYPE_LITTEXTURE:
9707                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9708                         {
9709                                 // two-pass lit texture with 2x rgbscale
9710                                 // first the lightmap pass
9711                                 R_Mesh_TexBind(0, r_texture_white);
9712                                 R_Mesh_TexMatrix(0, NULL);
9713                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9714                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9715                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9716                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9717                                 else if (FAKELIGHT_ENABLED)
9718                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9719                                 else if (rsurface.uselightmaptexture)
9720                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9721                                 else
9722                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9723                                 // then apply the texture to it
9724                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9725                                 R_Mesh_TexBind(0, layer->texture);
9726                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9727                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9728                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9729                                 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);
9730                         }
9731                         else
9732                         {
9733                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9734                                 R_Mesh_TexBind(0, layer->texture);
9735                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9736                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9737                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9738                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9739                                         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);
9740                                 else
9741                                         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);
9742                         }
9743                         break;
9744                 case TEXTURELAYERTYPE_TEXTURE:
9745                         // singletexture unlit texture with transparency support
9746                         R_Mesh_TexBind(0, layer->texture);
9747                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9748                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9749                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9750                         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);
9751                         break;
9752                 case TEXTURELAYERTYPE_FOG:
9753                         // singletexture fogging
9754                         if (layer->texture)
9755                         {
9756                                 R_Mesh_TexBind(0, layer->texture);
9757                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9758                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9759                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9760                         }
9761                         else
9762                         {
9763                                 R_Mesh_TexBind(0, 0);
9764                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9765                         }
9766                         // generate a color array for the fog pass
9767                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9768                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9769                         RSurf_DrawBatch();
9770                         break;
9771                 default:
9772                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9773                 }
9774         }
9775         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9776         {
9777                 GL_DepthFunc(GL_LEQUAL);
9778                 GL_AlphaTest(false);
9779         }
9780 }
9781
9782 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9783 {
9784         int vi;
9785         int j;
9786         r_vertexgeneric_t *batchvertex;
9787         float c[4];
9788
9789 //      R_Mesh_ResetTextureState();
9790         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9791
9792         if(rsurface.texture && rsurface.texture->currentskinframe)
9793         {
9794                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9795                 c[3] *= rsurface.texture->currentalpha;
9796         }
9797         else
9798         {
9799                 c[0] = 1;
9800                 c[1] = 0;
9801                 c[2] = 1;
9802                 c[3] = 1;
9803         }
9804
9805         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9806         {
9807                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9808                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9809                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9810         }
9811
9812         // brighten it up (as texture value 127 means "unlit")
9813         c[0] *= 2 * r_refdef.view.colorscale;
9814         c[1] *= 2 * r_refdef.view.colorscale;
9815         c[2] *= 2 * r_refdef.view.colorscale;
9816
9817         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9818                 c[3] *= r_wateralpha.value;
9819
9820         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9821         {
9822                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9823                 GL_DepthMask(false);
9824         }
9825         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9826         {
9827                 GL_BlendFunc(GL_ONE, GL_ONE);
9828                 GL_DepthMask(false);
9829         }
9830         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9831         {
9832                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9833                 GL_DepthMask(false);
9834         }
9835         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9836         {
9837                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9838                 GL_DepthMask(false);
9839         }
9840         else
9841         {
9842                 GL_BlendFunc(GL_ONE, GL_ZERO);
9843                 GL_DepthMask(writedepth);
9844         }
9845
9846         if (r_showsurfaces.integer == 3)
9847         {
9848                 rsurface.passcolor4f = NULL;
9849
9850                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9851                 {
9852                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9853
9854                         rsurface.passcolor4f = NULL;
9855                         rsurface.passcolor4f_vertexbuffer = 0;
9856                         rsurface.passcolor4f_bufferoffset = 0;
9857                 }
9858                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9859                 {
9860                         qboolean applycolor = true;
9861                         float one = 1.0;
9862
9863                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9864
9865                         r_refdef.lightmapintensity = 1;
9866                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9867                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9868                 }
9869                 else if (FAKELIGHT_ENABLED)
9870                 {
9871                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9872
9873                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9874                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9875                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9876                 }
9877                 else
9878                 {
9879                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9880
9881                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9882                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9883                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9884                 }
9885
9886                 if(!rsurface.passcolor4f)
9887                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9888
9889                 RSurf_DrawBatch_GL11_ApplyAmbient();
9890                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9891                 if(r_refdef.fogenabled)
9892                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9893                 RSurf_DrawBatch_GL11_ClampColor();
9894
9895                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9896                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9897                 RSurf_DrawBatch();
9898         }
9899         else if (!r_refdef.view.showdebug)
9900         {
9901                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9902                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9903                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9904                 {
9905                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9906                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9907                 }
9908                 R_Mesh_PrepareVertices_Generic_Unlock();
9909                 RSurf_DrawBatch();
9910         }
9911         else if (r_showsurfaces.integer == 4)
9912         {
9913                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9914                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9915                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9916                 {
9917                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9918                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9919                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9920                 }
9921                 R_Mesh_PrepareVertices_Generic_Unlock();
9922                 RSurf_DrawBatch();
9923         }
9924         else if (r_showsurfaces.integer == 2)
9925         {
9926                 const int *e;
9927                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9928                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9929                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9930                 {
9931                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9932                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9933                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9934                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9935                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9936                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9937                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9938                 }
9939                 R_Mesh_PrepareVertices_Generic_Unlock();
9940                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9941         }
9942         else
9943         {
9944                 int texturesurfaceindex;
9945                 int k;
9946                 const msurface_t *surface;
9947                 float surfacecolor4f[4];
9948                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9949                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9950                 vi = 0;
9951                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9952                 {
9953                         surface = texturesurfacelist[texturesurfaceindex];
9954                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9955                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9956                         for (j = 0;j < surface->num_vertices;j++)
9957                         {
9958                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9959                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9960                                 vi++;
9961                         }
9962                 }
9963                 R_Mesh_PrepareVertices_Generic_Unlock();
9964                 RSurf_DrawBatch();
9965         }
9966 }
9967
9968 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9969 {
9970         CHECKGLERROR
9971         RSurf_SetupDepthAndCulling();
9972         if (r_showsurfaces.integer)
9973         {
9974                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9975                 return;
9976         }
9977         switch (vid.renderpath)
9978         {
9979         case RENDERPATH_GL20:
9980         case RENDERPATH_D3D9:
9981         case RENDERPATH_D3D10:
9982         case RENDERPATH_D3D11:
9983         case RENDERPATH_SOFT:
9984         case RENDERPATH_GLES2:
9985                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9986                 break;
9987         case RENDERPATH_GL13:
9988         case RENDERPATH_GLES1:
9989                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9990                 break;
9991         case RENDERPATH_GL11:
9992                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9993                 break;
9994         }
9995         CHECKGLERROR
9996 }
9997
9998 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9999 {
10000         CHECKGLERROR
10001         RSurf_SetupDepthAndCulling();
10002         if (r_showsurfaces.integer)
10003         {
10004                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10005                 return;
10006         }
10007         switch (vid.renderpath)
10008         {
10009         case RENDERPATH_GL20:
10010         case RENDERPATH_D3D9:
10011         case RENDERPATH_D3D10:
10012         case RENDERPATH_D3D11:
10013         case RENDERPATH_SOFT:
10014         case RENDERPATH_GLES2:
10015                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10016                 break;
10017         case RENDERPATH_GL13:
10018         case RENDERPATH_GLES1:
10019                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10020                 break;
10021         case RENDERPATH_GL11:
10022                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10023                 break;
10024         }
10025         CHECKGLERROR
10026 }
10027
10028 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10029 {
10030         int i, j;
10031         int texturenumsurfaces, endsurface;
10032         texture_t *texture;
10033         const msurface_t *surface;
10034         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10035
10036         // if the model is static it doesn't matter what value we give for
10037         // wantnormals and wanttangents, so this logic uses only rules applicable
10038         // to a model, knowing that they are meaningless otherwise
10039         if (ent == r_refdef.scene.worldentity)
10040                 RSurf_ActiveWorldEntity();
10041         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10042                 RSurf_ActiveModelEntity(ent, false, false, false);
10043         else
10044         {
10045                 switch (vid.renderpath)
10046                 {
10047                 case RENDERPATH_GL20:
10048                 case RENDERPATH_D3D9:
10049                 case RENDERPATH_D3D10:
10050                 case RENDERPATH_D3D11:
10051                 case RENDERPATH_SOFT:
10052                 case RENDERPATH_GLES2:
10053                         RSurf_ActiveModelEntity(ent, true, true, false);
10054                         break;
10055                 case RENDERPATH_GL11:
10056                 case RENDERPATH_GL13:
10057                 case RENDERPATH_GLES1:
10058                         RSurf_ActiveModelEntity(ent, true, false, false);
10059                         break;
10060                 }
10061         }
10062
10063         if (r_transparentdepthmasking.integer)
10064         {
10065                 qboolean setup = false;
10066                 for (i = 0;i < numsurfaces;i = j)
10067                 {
10068                         j = i + 1;
10069                         surface = rsurface.modelsurfaces + surfacelist[i];
10070                         texture = surface->texture;
10071                         rsurface.texture = R_GetCurrentTexture(texture);
10072                         rsurface.lightmaptexture = NULL;
10073                         rsurface.deluxemaptexture = NULL;
10074                         rsurface.uselightmaptexture = false;
10075                         // scan ahead until we find a different texture
10076                         endsurface = min(i + 1024, numsurfaces);
10077                         texturenumsurfaces = 0;
10078                         texturesurfacelist[texturenumsurfaces++] = surface;
10079                         for (;j < endsurface;j++)
10080                         {
10081                                 surface = rsurface.modelsurfaces + surfacelist[j];
10082                                 if (texture != surface->texture)
10083                                         break;
10084                                 texturesurfacelist[texturenumsurfaces++] = surface;
10085                         }
10086                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10087                                 continue;
10088                         // render the range of surfaces as depth
10089                         if (!setup)
10090                         {
10091                                 setup = true;
10092                                 GL_ColorMask(0,0,0,0);
10093                                 GL_Color(1,1,1,1);
10094                                 GL_DepthTest(true);
10095                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10096                                 GL_DepthMask(true);
10097 //                              R_Mesh_ResetTextureState();
10098                                 R_SetupShader_DepthOrShadow();
10099                         }
10100                         RSurf_SetupDepthAndCulling();
10101                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10102                         if (rsurface.batchvertex3fbuffer)
10103                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10104                         else
10105                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10106                         RSurf_DrawBatch();
10107                 }
10108                 if (setup)
10109                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10110         }
10111
10112         for (i = 0;i < numsurfaces;i = j)
10113         {
10114                 j = i + 1;
10115                 surface = rsurface.modelsurfaces + surfacelist[i];
10116                 texture = surface->texture;
10117                 rsurface.texture = R_GetCurrentTexture(texture);
10118                 // scan ahead until we find a different texture
10119                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10120                 texturenumsurfaces = 0;
10121                 texturesurfacelist[texturenumsurfaces++] = surface;
10122                 if(FAKELIGHT_ENABLED)
10123                 {
10124                         rsurface.lightmaptexture = NULL;
10125                         rsurface.deluxemaptexture = NULL;
10126                         rsurface.uselightmaptexture = false;
10127                         for (;j < endsurface;j++)
10128                         {
10129                                 surface = rsurface.modelsurfaces + surfacelist[j];
10130                                 if (texture != surface->texture)
10131                                         break;
10132                                 texturesurfacelist[texturenumsurfaces++] = surface;
10133                         }
10134                 }
10135                 else
10136                 {
10137                         rsurface.lightmaptexture = surface->lightmaptexture;
10138                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10139                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10140                         for (;j < endsurface;j++)
10141                         {
10142                                 surface = rsurface.modelsurfaces + surfacelist[j];
10143                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10144                                         break;
10145                                 texturesurfacelist[texturenumsurfaces++] = surface;
10146                         }
10147                 }
10148                 // render the range of surfaces
10149                 if (ent == r_refdef.scene.worldentity)
10150                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10151                 else
10152                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10153         }
10154         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10155 }
10156
10157 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10158 {
10159         // transparent surfaces get pushed off into the transparent queue
10160         int surfacelistindex;
10161         const msurface_t *surface;
10162         vec3_t tempcenter, center;
10163         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10164         {
10165                 surface = texturesurfacelist[surfacelistindex];
10166                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10167                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10168                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10169                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10170                 if (queueentity->transparent_offset) // transparent offset
10171                 {
10172                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10173                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10174                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10175                 }
10176                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10177         }
10178 }
10179
10180 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10181 {
10182         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10183                 return;
10184         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10185                 return;
10186         RSurf_SetupDepthAndCulling();
10187         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10188         if (rsurface.batchvertex3fbuffer)
10189                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10190         else
10191                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10192         RSurf_DrawBatch();
10193 }
10194
10195 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10196 {
10197         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10198         CHECKGLERROR
10199         if (depthonly)
10200                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10201         else if (prepass)
10202         {
10203                 if (!rsurface.texture->currentnumlayers)
10204                         return;
10205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10206                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10207                 else
10208                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10209         }
10210         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10211                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10212         else if (!rsurface.texture->currentnumlayers)
10213                 return;
10214         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10215         {
10216                 // in the deferred case, transparent surfaces were queued during prepass
10217                 if (!r_shadow_usingdeferredprepass)
10218                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10219         }
10220         else
10221         {
10222                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10223                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10224         }
10225         CHECKGLERROR
10226 }
10227
10228 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10229 {
10230         int i, j;
10231         texture_t *texture;
10232         R_FrameData_SetMark();
10233         // break the surface list down into batches by texture and use of lightmapping
10234         for (i = 0;i < numsurfaces;i = j)
10235         {
10236                 j = i + 1;
10237                 // texture is the base texture pointer, rsurface.texture is the
10238                 // current frame/skin the texture is directing us to use (for example
10239                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10240                 // use skin 1 instead)
10241                 texture = surfacelist[i]->texture;
10242                 rsurface.texture = R_GetCurrentTexture(texture);
10243                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10244                 {
10245                         // if this texture is not the kind we want, skip ahead to the next one
10246                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10247                                 ;
10248                         continue;
10249                 }
10250                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10251                 {
10252                         rsurface.lightmaptexture = NULL;
10253                         rsurface.deluxemaptexture = NULL;
10254                         rsurface.uselightmaptexture = false;
10255                         // simply scan ahead until we find a different texture or lightmap state
10256                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10257                                 ;
10258                 }
10259                 else
10260                 {
10261                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10262                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10263                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10264                         // simply scan ahead until we find a different texture or lightmap state
10265                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10266                                 ;
10267                 }
10268                 // render the range of surfaces
10269                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10270         }
10271         R_FrameData_ReturnToMark();
10272 }
10273
10274 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10275 {
10276         CHECKGLERROR
10277         if (depthonly)
10278                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10279         else if (prepass)
10280         {
10281                 if (!rsurface.texture->currentnumlayers)
10282                         return;
10283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10284                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10285                 else
10286                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10287         }
10288         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10289                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10290         else if (!rsurface.texture->currentnumlayers)
10291                 return;
10292         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10293         {
10294                 // in the deferred case, transparent surfaces were queued during prepass
10295                 if (!r_shadow_usingdeferredprepass)
10296                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10297         }
10298         else
10299         {
10300                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10301                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10302         }
10303         CHECKGLERROR
10304 }
10305
10306 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10307 {
10308         int i, j;
10309         texture_t *texture;
10310         R_FrameData_SetMark();
10311         // break the surface list down into batches by texture and use of lightmapping
10312         for (i = 0;i < numsurfaces;i = j)
10313         {
10314                 j = i + 1;
10315                 // texture is the base texture pointer, rsurface.texture is the
10316                 // current frame/skin the texture is directing us to use (for example
10317                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10318                 // use skin 1 instead)
10319                 texture = surfacelist[i]->texture;
10320                 rsurface.texture = R_GetCurrentTexture(texture);
10321                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10322                 {
10323                         // if this texture is not the kind we want, skip ahead to the next one
10324                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10325                                 ;
10326                         continue;
10327                 }
10328                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10329                 {
10330                         rsurface.lightmaptexture = NULL;
10331                         rsurface.deluxemaptexture = NULL;
10332                         rsurface.uselightmaptexture = false;
10333                         // simply scan ahead until we find a different texture or lightmap state
10334                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10335                                 ;
10336                 }
10337                 else
10338                 {
10339                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10340                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10341                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10342                         // simply scan ahead until we find a different texture or lightmap state
10343                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10344                                 ;
10345                 }
10346                 // render the range of surfaces
10347                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10348         }
10349         R_FrameData_ReturnToMark();
10350 }
10351
10352 float locboxvertex3f[6*4*3] =
10353 {
10354         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10355         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10356         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10357         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10358         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10359         1,0,0, 0,0,0, 0,1,0, 1,1,0
10360 };
10361
10362 unsigned short locboxelements[6*2*3] =
10363 {
10364          0, 1, 2, 0, 2, 3,
10365          4, 5, 6, 4, 6, 7,
10366          8, 9,10, 8,10,11,
10367         12,13,14, 12,14,15,
10368         16,17,18, 16,18,19,
10369         20,21,22, 20,22,23
10370 };
10371
10372 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10373 {
10374         int i, j;
10375         cl_locnode_t *loc = (cl_locnode_t *)ent;
10376         vec3_t mins, size;
10377         float vertex3f[6*4*3];
10378         CHECKGLERROR
10379         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10380         GL_DepthMask(false);
10381         GL_DepthRange(0, 1);
10382         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10383         GL_DepthTest(true);
10384         GL_CullFace(GL_NONE);
10385         R_EntityMatrix(&identitymatrix);
10386
10387 //      R_Mesh_ResetTextureState();
10388
10389         i = surfacelist[0];
10390         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10391                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10392                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10393                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10394
10395         if (VectorCompare(loc->mins, loc->maxs))
10396         {
10397                 VectorSet(size, 2, 2, 2);
10398                 VectorMA(loc->mins, -0.5f, size, mins);
10399         }
10400         else
10401         {
10402                 VectorCopy(loc->mins, mins);
10403                 VectorSubtract(loc->maxs, loc->mins, size);
10404         }
10405
10406         for (i = 0;i < 6*4*3;)
10407                 for (j = 0;j < 3;j++, i++)
10408                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10409
10410         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10411         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10412         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10413 }
10414
10415 void R_DrawLocs(void)
10416 {
10417         int index;
10418         cl_locnode_t *loc, *nearestloc;
10419         vec3_t center;
10420         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10421         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10422         {
10423                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10424                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10425         }
10426 }
10427
10428 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10429 {
10430         if (decalsystem->decals)
10431                 Mem_Free(decalsystem->decals);
10432         memset(decalsystem, 0, sizeof(*decalsystem));
10433 }
10434
10435 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)
10436 {
10437         tridecal_t *decal;
10438         tridecal_t *decals;
10439         int i;
10440
10441         // expand or initialize the system
10442         if (decalsystem->maxdecals <= decalsystem->numdecals)
10443         {
10444                 decalsystem_t old = *decalsystem;
10445                 qboolean useshortelements;
10446                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10447                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10448                 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)));
10449                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10450                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10451                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10452                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10453                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10454                 if (decalsystem->numdecals)
10455                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10456                 if (old.decals)
10457                         Mem_Free(old.decals);
10458                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10459                         decalsystem->element3i[i] = i;
10460                 if (useshortelements)
10461                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10462                                 decalsystem->element3s[i] = i;
10463         }
10464
10465         // grab a decal and search for another free slot for the next one
10466         decals = decalsystem->decals;
10467         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10468         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10469                 ;
10470         decalsystem->freedecal = i;
10471         if (decalsystem->numdecals <= i)
10472                 decalsystem->numdecals = i + 1;
10473
10474         // initialize the decal
10475         decal->lived = 0;
10476         decal->triangleindex = triangleindex;
10477         decal->surfaceindex = surfaceindex;
10478         decal->decalsequence = decalsequence;
10479         decal->color4f[0][0] = c0[0];
10480         decal->color4f[0][1] = c0[1];
10481         decal->color4f[0][2] = c0[2];
10482         decal->color4f[0][3] = 1;
10483         decal->color4f[1][0] = c1[0];
10484         decal->color4f[1][1] = c1[1];
10485         decal->color4f[1][2] = c1[2];
10486         decal->color4f[1][3] = 1;
10487         decal->color4f[2][0] = c2[0];
10488         decal->color4f[2][1] = c2[1];
10489         decal->color4f[2][2] = c2[2];
10490         decal->color4f[2][3] = 1;
10491         decal->vertex3f[0][0] = v0[0];
10492         decal->vertex3f[0][1] = v0[1];
10493         decal->vertex3f[0][2] = v0[2];
10494         decal->vertex3f[1][0] = v1[0];
10495         decal->vertex3f[1][1] = v1[1];
10496         decal->vertex3f[1][2] = v1[2];
10497         decal->vertex3f[2][0] = v2[0];
10498         decal->vertex3f[2][1] = v2[1];
10499         decal->vertex3f[2][2] = v2[2];
10500         decal->texcoord2f[0][0] = t0[0];
10501         decal->texcoord2f[0][1] = t0[1];
10502         decal->texcoord2f[1][0] = t1[0];
10503         decal->texcoord2f[1][1] = t1[1];
10504         decal->texcoord2f[2][0] = t2[0];
10505         decal->texcoord2f[2][1] = t2[1];
10506         TriangleNormal(v0, v1, v2, decal->plane);
10507         VectorNormalize(decal->plane);
10508         decal->plane[3] = DotProduct(v0, decal->plane);
10509 }
10510
10511 extern cvar_t cl_decals_bias;
10512 extern cvar_t cl_decals_models;
10513 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10514 // baseparms, parms, temps
10515 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)
10516 {
10517         int cornerindex;
10518         int index;
10519         float v[9][3];
10520         const float *vertex3f;
10521         const float *normal3f;
10522         int numpoints;
10523         float points[2][9][3];
10524         float temp[3];
10525         float tc[9][2];
10526         float f;
10527         float c[9][4];
10528         const int *e;
10529
10530         e = rsurface.modelelement3i + 3*triangleindex;
10531
10532         vertex3f = rsurface.modelvertex3f;
10533         normal3f = rsurface.modelnormal3f;
10534
10535         if (normal3f)
10536         {
10537                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10538                 {
10539                         index = 3*e[cornerindex];
10540                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10541                 }
10542         }
10543         else
10544         {
10545                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10546                 {
10547                         index = 3*e[cornerindex];
10548                         VectorCopy(vertex3f + index, v[cornerindex]);
10549                 }
10550         }
10551
10552         // cull backfaces
10553         //TriangleNormal(v[0], v[1], v[2], normal);
10554         //if (DotProduct(normal, localnormal) < 0.0f)
10555         //      continue;
10556         // clip by each of the box planes formed from the projection matrix
10557         // if anything survives, we emit the decal
10558         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]);
10559         if (numpoints < 3)
10560                 return;
10561         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]);
10562         if (numpoints < 3)
10563                 return;
10564         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]);
10565         if (numpoints < 3)
10566                 return;
10567         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]);
10568         if (numpoints < 3)
10569                 return;
10570         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]);
10571         if (numpoints < 3)
10572                 return;
10573         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]);
10574         if (numpoints < 3)
10575                 return;
10576         // some part of the triangle survived, so we have to accept it...
10577         if (dynamic)
10578         {
10579                 // dynamic always uses the original triangle
10580                 numpoints = 3;
10581                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10582                 {
10583                         index = 3*e[cornerindex];
10584                         VectorCopy(vertex3f + index, v[cornerindex]);
10585                 }
10586         }
10587         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10588         {
10589                 // convert vertex positions to texcoords
10590                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10591                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10592                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10593                 // calculate distance fade from the projection origin
10594                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10595                 f = bound(0.0f, f, 1.0f);
10596                 c[cornerindex][0] = r * f;
10597                 c[cornerindex][1] = g * f;
10598                 c[cornerindex][2] = b * f;
10599                 c[cornerindex][3] = 1.0f;
10600                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10601         }
10602         if (dynamic)
10603                 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);
10604         else
10605                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10606                         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);
10607 }
10608 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)
10609 {
10610         matrix4x4_t projection;
10611         decalsystem_t *decalsystem;
10612         qboolean dynamic;
10613         dp_model_t *model;
10614         const msurface_t *surface;
10615         const msurface_t *surfaces;
10616         const int *surfacelist;
10617         const texture_t *texture;
10618         int numtriangles;
10619         int numsurfacelist;
10620         int surfacelistindex;
10621         int surfaceindex;
10622         int triangleindex;
10623         float localorigin[3];
10624         float localnormal[3];
10625         float localmins[3];
10626         float localmaxs[3];
10627         float localsize;
10628         //float normal[3];
10629         float planes[6][4];
10630         float angles[3];
10631         bih_t *bih;
10632         int bih_triangles_count;
10633         int bih_triangles[256];
10634         int bih_surfaces[256];
10635
10636         decalsystem = &ent->decalsystem;
10637         model = ent->model;
10638         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10639         {
10640                 R_DecalSystem_Reset(&ent->decalsystem);
10641                 return;
10642         }
10643
10644         if (!model->brush.data_leafs && !cl_decals_models.integer)
10645         {
10646                 if (decalsystem->model)
10647                         R_DecalSystem_Reset(decalsystem);
10648                 return;
10649         }
10650
10651         if (decalsystem->model != model)
10652                 R_DecalSystem_Reset(decalsystem);
10653         decalsystem->model = model;
10654
10655         RSurf_ActiveModelEntity(ent, true, false, false);
10656
10657         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10658         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10659         VectorNormalize(localnormal);
10660         localsize = worldsize*rsurface.inversematrixscale;
10661         localmins[0] = localorigin[0] - localsize;
10662         localmins[1] = localorigin[1] - localsize;
10663         localmins[2] = localorigin[2] - localsize;
10664         localmaxs[0] = localorigin[0] + localsize;
10665         localmaxs[1] = localorigin[1] + localsize;
10666         localmaxs[2] = localorigin[2] + localsize;
10667
10668         //VectorCopy(localnormal, planes[4]);
10669         //VectorVectors(planes[4], planes[2], planes[0]);
10670         AnglesFromVectors(angles, localnormal, NULL, false);
10671         AngleVectors(angles, planes[0], planes[2], planes[4]);
10672         VectorNegate(planes[0], planes[1]);
10673         VectorNegate(planes[2], planes[3]);
10674         VectorNegate(planes[4], planes[5]);
10675         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10676         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10677         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10678         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10679         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10680         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10681
10682 #if 1
10683 // works
10684 {
10685         matrix4x4_t forwardprojection;
10686         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10687         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10688 }
10689 #else
10690 // broken
10691 {
10692         float projectionvector[4][3];
10693         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10694         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10695         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10696         projectionvector[0][0] = planes[0][0] * ilocalsize;
10697         projectionvector[0][1] = planes[1][0] * ilocalsize;
10698         projectionvector[0][2] = planes[2][0] * ilocalsize;
10699         projectionvector[1][0] = planes[0][1] * ilocalsize;
10700         projectionvector[1][1] = planes[1][1] * ilocalsize;
10701         projectionvector[1][2] = planes[2][1] * ilocalsize;
10702         projectionvector[2][0] = planes[0][2] * ilocalsize;
10703         projectionvector[2][1] = planes[1][2] * ilocalsize;
10704         projectionvector[2][2] = planes[2][2] * ilocalsize;
10705         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10706         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10707         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10708         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10709 }
10710 #endif
10711
10712         dynamic = model->surfmesh.isanimated;
10713         numsurfacelist = model->nummodelsurfaces;
10714         surfacelist = model->sortedmodelsurfaces;
10715         surfaces = model->data_surfaces;
10716
10717         bih = NULL;
10718         bih_triangles_count = -1;
10719         if(!dynamic)
10720         {
10721                 if(model->render_bih.numleafs)
10722                         bih = &model->render_bih;
10723                 else if(model->collision_bih.numleafs)
10724                         bih = &model->collision_bih;
10725         }
10726         if(bih)
10727                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10728         if(bih_triangles_count == 0)
10729                 return;
10730         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10731                 return;
10732         if(bih_triangles_count > 0)
10733         {
10734                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10735                 {
10736                         surfaceindex = bih_surfaces[triangleindex];
10737                         surface = surfaces + surfaceindex;
10738                         texture = surface->texture;
10739                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10740                                 continue;
10741                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10742                                 continue;
10743                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10744                 }
10745         }
10746         else
10747         {
10748                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10749                 {
10750                         surfaceindex = surfacelist[surfacelistindex];
10751                         surface = surfaces + surfaceindex;
10752                         // check cull box first because it rejects more than any other check
10753                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10754                                 continue;
10755                         // skip transparent surfaces
10756                         texture = surface->texture;
10757                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10758                                 continue;
10759                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10760                                 continue;
10761                         numtriangles = surface->num_triangles;
10762                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10763                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10764                 }
10765         }
10766 }
10767
10768 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10769 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)
10770 {
10771         int renderentityindex;
10772         float worldmins[3];
10773         float worldmaxs[3];
10774         entity_render_t *ent;
10775
10776         if (!cl_decals_newsystem.integer)
10777                 return;
10778
10779         worldmins[0] = worldorigin[0] - worldsize;
10780         worldmins[1] = worldorigin[1] - worldsize;
10781         worldmins[2] = worldorigin[2] - worldsize;
10782         worldmaxs[0] = worldorigin[0] + worldsize;
10783         worldmaxs[1] = worldorigin[1] + worldsize;
10784         worldmaxs[2] = worldorigin[2] + worldsize;
10785
10786         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10787
10788         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10789         {
10790                 ent = r_refdef.scene.entities[renderentityindex];
10791                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10792                         continue;
10793
10794                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10795         }
10796 }
10797
10798 typedef struct r_decalsystem_splatqueue_s
10799 {
10800         vec3_t worldorigin;
10801         vec3_t worldnormal;
10802         float color[4];
10803         float tcrange[4];
10804         float worldsize;
10805         int decalsequence;
10806 }
10807 r_decalsystem_splatqueue_t;
10808
10809 int r_decalsystem_numqueued = 0;
10810 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10811
10812 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)
10813 {
10814         r_decalsystem_splatqueue_t *queue;
10815
10816         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10817                 return;
10818
10819         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10820         VectorCopy(worldorigin, queue->worldorigin);
10821         VectorCopy(worldnormal, queue->worldnormal);
10822         Vector4Set(queue->color, r, g, b, a);
10823         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10824         queue->worldsize = worldsize;
10825         queue->decalsequence = cl.decalsequence++;
10826 }
10827
10828 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10829 {
10830         int i;
10831         r_decalsystem_splatqueue_t *queue;
10832
10833         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10834                 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);
10835         r_decalsystem_numqueued = 0;
10836 }
10837
10838 extern cvar_t cl_decals_max;
10839 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10840 {
10841         int i;
10842         decalsystem_t *decalsystem = &ent->decalsystem;
10843         int numdecals;
10844         int killsequence;
10845         tridecal_t *decal;
10846         float frametime;
10847         float lifetime;
10848
10849         if (!decalsystem->numdecals)
10850                 return;
10851
10852         if (r_showsurfaces.integer)
10853                 return;
10854
10855         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10856         {
10857                 R_DecalSystem_Reset(decalsystem);
10858                 return;
10859         }
10860
10861         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10862         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10863
10864         if (decalsystem->lastupdatetime)
10865                 frametime = (cl.time - decalsystem->lastupdatetime);
10866         else
10867                 frametime = 0;
10868         decalsystem->lastupdatetime = cl.time;
10869         decal = decalsystem->decals;
10870         numdecals = decalsystem->numdecals;
10871
10872         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10873         {
10874                 if (decal->color4f[0][3])
10875                 {
10876                         decal->lived += frametime;
10877                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10878                         {
10879                                 memset(decal, 0, sizeof(*decal));
10880                                 if (decalsystem->freedecal > i)
10881                                         decalsystem->freedecal = i;
10882                         }
10883                 }
10884         }
10885         decal = decalsystem->decals;
10886         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10887                 numdecals--;
10888
10889         // collapse the array by shuffling the tail decals into the gaps
10890         for (;;)
10891         {
10892                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10893                         decalsystem->freedecal++;
10894                 if (decalsystem->freedecal == numdecals)
10895                         break;
10896                 decal[decalsystem->freedecal] = decal[--numdecals];
10897         }
10898
10899         decalsystem->numdecals = numdecals;
10900
10901         if (numdecals <= 0)
10902         {
10903                 // if there are no decals left, reset decalsystem
10904                 R_DecalSystem_Reset(decalsystem);
10905         }
10906 }
10907
10908 extern skinframe_t *decalskinframe;
10909 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10910 {
10911         int i;
10912         decalsystem_t *decalsystem = &ent->decalsystem;
10913         int numdecals;
10914         tridecal_t *decal;
10915         float faderate;
10916         float alpha;
10917         float *v3f;
10918         float *c4f;
10919         float *t2f;
10920         const int *e;
10921         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10922         int numtris = 0;
10923
10924         numdecals = decalsystem->numdecals;
10925         if (!numdecals)
10926                 return;
10927
10928         if (r_showsurfaces.integer)
10929                 return;
10930
10931         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10932         {
10933                 R_DecalSystem_Reset(decalsystem);
10934                 return;
10935         }
10936
10937         // if the model is static it doesn't matter what value we give for
10938         // wantnormals and wanttangents, so this logic uses only rules applicable
10939         // to a model, knowing that they are meaningless otherwise
10940         if (ent == r_refdef.scene.worldentity)
10941                 RSurf_ActiveWorldEntity();
10942         else
10943                 RSurf_ActiveModelEntity(ent, false, false, false);
10944
10945         decalsystem->lastupdatetime = cl.time;
10946         decal = decalsystem->decals;
10947
10948         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10949
10950         // update vertex positions for animated models
10951         v3f = decalsystem->vertex3f;
10952         c4f = decalsystem->color4f;
10953         t2f = decalsystem->texcoord2f;
10954         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10955         {
10956                 if (!decal->color4f[0][3])
10957                         continue;
10958
10959                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10960                         continue;
10961
10962                 // skip backfaces
10963                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10964                         continue;
10965
10966                 // update color values for fading decals
10967                 if (decal->lived >= cl_decals_time.value)
10968                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10969                 else
10970                         alpha = 1.0f;
10971
10972                 c4f[ 0] = decal->color4f[0][0] * alpha;
10973                 c4f[ 1] = decal->color4f[0][1] * alpha;
10974                 c4f[ 2] = decal->color4f[0][2] * alpha;
10975                 c4f[ 3] = 1;
10976                 c4f[ 4] = decal->color4f[1][0] * alpha;
10977                 c4f[ 5] = decal->color4f[1][1] * alpha;
10978                 c4f[ 6] = decal->color4f[1][2] * alpha;
10979                 c4f[ 7] = 1;
10980                 c4f[ 8] = decal->color4f[2][0] * alpha;
10981                 c4f[ 9] = decal->color4f[2][1] * alpha;
10982                 c4f[10] = decal->color4f[2][2] * alpha;
10983                 c4f[11] = 1;
10984
10985                 t2f[0] = decal->texcoord2f[0][0];
10986                 t2f[1] = decal->texcoord2f[0][1];
10987                 t2f[2] = decal->texcoord2f[1][0];
10988                 t2f[3] = decal->texcoord2f[1][1];
10989                 t2f[4] = decal->texcoord2f[2][0];
10990                 t2f[5] = decal->texcoord2f[2][1];
10991
10992                 // update vertex positions for animated models
10993                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10994                 {
10995                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10996                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10997                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10998                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10999                 }
11000                 else
11001                 {
11002                         VectorCopy(decal->vertex3f[0], v3f);
11003                         VectorCopy(decal->vertex3f[1], v3f + 3);
11004                         VectorCopy(decal->vertex3f[2], v3f + 6);
11005                 }
11006
11007                 if (r_refdef.fogenabled)
11008                 {
11009                         alpha = RSurf_FogVertex(v3f);
11010                         VectorScale(c4f, alpha, c4f);
11011                         alpha = RSurf_FogVertex(v3f + 3);
11012                         VectorScale(c4f + 4, alpha, c4f + 4);
11013                         alpha = RSurf_FogVertex(v3f + 6);
11014                         VectorScale(c4f + 8, alpha, c4f + 8);
11015                 }
11016
11017                 v3f += 9;
11018                 c4f += 12;
11019                 t2f += 6;
11020                 numtris++;
11021         }
11022
11023         if (numtris > 0)
11024         {
11025                 r_refdef.stats.drawndecals += numtris;
11026
11027                 // now render the decals all at once
11028                 // (this assumes they all use one particle font texture!)
11029                 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);
11030 //              R_Mesh_ResetTextureState();
11031                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11032                 GL_DepthMask(false);
11033                 GL_DepthRange(0, 1);
11034                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11035                 GL_DepthTest(true);
11036                 GL_CullFace(GL_NONE);
11037                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11038                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11039                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11040         }
11041 }
11042
11043 static void R_DrawModelDecals(void)
11044 {
11045         int i, numdecals;
11046
11047         // fade faster when there are too many decals
11048         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11049         for (i = 0;i < r_refdef.scene.numentities;i++)
11050                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11051
11052         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11053         for (i = 0;i < r_refdef.scene.numentities;i++)
11054                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11055                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11056
11057         R_DecalSystem_ApplySplatEntitiesQueue();
11058
11059         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11060         for (i = 0;i < r_refdef.scene.numentities;i++)
11061                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11062
11063         r_refdef.stats.totaldecals += numdecals;
11064
11065         if (r_showsurfaces.integer)
11066                 return;
11067
11068         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11069
11070         for (i = 0;i < r_refdef.scene.numentities;i++)
11071         {
11072                 if (!r_refdef.viewcache.entityvisible[i])
11073                         continue;
11074                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11075                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11076         }
11077 }
11078
11079 extern cvar_t mod_collision_bih;
11080 void R_DrawDebugModel(void)
11081 {
11082         entity_render_t *ent = rsurface.entity;
11083         int i, j, k, l, flagsmask;
11084         const msurface_t *surface;
11085         dp_model_t *model = ent->model;
11086         vec3_t v;
11087
11088         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11089                 return;
11090
11091         if (r_showoverdraw.value > 0)
11092         {
11093                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11094                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11095                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11096                 GL_DepthTest(false);
11097                 GL_DepthMask(false);
11098                 GL_DepthRange(0, 1);
11099                 GL_BlendFunc(GL_ONE, GL_ONE);
11100                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11101                 {
11102                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11103                                 continue;
11104                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11105                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11106                         {
11107                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11108                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11109                                 if (!rsurface.texture->currentlayers->depthmask)
11110                                         GL_Color(c, 0, 0, 1.0f);
11111                                 else if (ent == r_refdef.scene.worldentity)
11112                                         GL_Color(c, c, c, 1.0f);
11113                                 else
11114                                         GL_Color(0, c, 0, 1.0f);
11115                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11116                                 RSurf_DrawBatch();
11117                         }
11118                 }
11119                 rsurface.texture = NULL;
11120         }
11121
11122         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11123
11124 //      R_Mesh_ResetTextureState();
11125         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11126         GL_DepthRange(0, 1);
11127         GL_DepthTest(!r_showdisabledepthtest.integer);
11128         GL_DepthMask(false);
11129         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11130
11131         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11132         {
11133                 int triangleindex;
11134                 int bihleafindex;
11135                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11136                 const q3mbrush_t *brush;
11137                 const bih_t *bih = &model->collision_bih;
11138                 const bih_leaf_t *bihleaf;
11139                 float vertex3f[3][3];
11140                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11141                 cullbox = false;
11142                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11143                 {
11144                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11145                                 continue;
11146                         switch (bihleaf->type)
11147                         {
11148                         case BIH_BRUSH:
11149                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11150                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11151                                 {
11152                                         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);
11153                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11154                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11155                                 }
11156                                 break;
11157                         case BIH_COLLISIONTRIANGLE:
11158                                 triangleindex = bihleaf->itemindex;
11159                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11160                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11161                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11162                                 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);
11163                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11164                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11165                                 break;
11166                         case BIH_RENDERTRIANGLE:
11167                                 triangleindex = bihleaf->itemindex;
11168                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11169                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11170                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11171                                 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);
11172                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11173                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11174                                 break;
11175                         }
11176                 }
11177         }
11178
11179         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11180
11181         if (r_showtris.integer && qglPolygonMode)
11182         {
11183                 if (r_showdisabledepthtest.integer)
11184                 {
11185                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11186                         GL_DepthMask(false);
11187                 }
11188                 else
11189                 {
11190                         GL_BlendFunc(GL_ONE, GL_ZERO);
11191                         GL_DepthMask(true);
11192                 }
11193                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11194                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11195                 {
11196                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11197                                 continue;
11198                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11199                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11200                         {
11201                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11202                                 if (!rsurface.texture->currentlayers->depthmask)
11203                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11204                                 else if (ent == r_refdef.scene.worldentity)
11205                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11206                                 else
11207                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11208                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11209                                 RSurf_DrawBatch();
11210                         }
11211                 }
11212                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11213                 rsurface.texture = NULL;
11214         }
11215
11216         if (r_shownormals.value != 0 && qglBegin)
11217         {
11218                 if (r_showdisabledepthtest.integer)
11219                 {
11220                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11221                         GL_DepthMask(false);
11222                 }
11223                 else
11224                 {
11225                         GL_BlendFunc(GL_ONE, GL_ZERO);
11226                         GL_DepthMask(true);
11227                 }
11228                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11229                 {
11230                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11231                                 continue;
11232                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11233                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11234                         {
11235                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11236                                 qglBegin(GL_LINES);
11237                                 if (r_shownormals.value < 0)
11238                                 {
11239                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11240                                         {
11241                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11242                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11243                                                 qglVertex3f(v[0], v[1], v[2]);
11244                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11245                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11246                                                 qglVertex3f(v[0], v[1], v[2]);
11247                                         }
11248                                 }
11249                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11250                                 {
11251                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11252                                         {
11253                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11254                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11255                                                 qglVertex3f(v[0], v[1], v[2]);
11256                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11257                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11258                                                 qglVertex3f(v[0], v[1], v[2]);
11259                                         }
11260                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11261                                         {
11262                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11263                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11264                                                 qglVertex3f(v[0], v[1], v[2]);
11265                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11266                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11267                                                 qglVertex3f(v[0], v[1], v[2]);
11268                                         }
11269                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11270                                         {
11271                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11272                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11273                                                 qglVertex3f(v[0], v[1], v[2]);
11274                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11275                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11276                                                 qglVertex3f(v[0], v[1], v[2]);
11277                                         }
11278                                 }
11279                                 qglEnd();
11280                                 CHECKGLERROR
11281                         }
11282                 }
11283                 rsurface.texture = NULL;
11284         }
11285 }
11286
11287 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11288 int r_maxsurfacelist = 0;
11289 const msurface_t **r_surfacelist = NULL;
11290 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11291 {
11292         int i, j, endj, flagsmask;
11293         dp_model_t *model = r_refdef.scene.worldmodel;
11294         msurface_t *surfaces;
11295         unsigned char *update;
11296         int numsurfacelist = 0;
11297         if (model == NULL)
11298                 return;
11299
11300         if (r_maxsurfacelist < model->num_surfaces)
11301         {
11302                 r_maxsurfacelist = model->num_surfaces;
11303                 if (r_surfacelist)
11304                         Mem_Free((msurface_t**)r_surfacelist);
11305                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11306         }
11307
11308         RSurf_ActiveWorldEntity();
11309
11310         surfaces = model->data_surfaces;
11311         update = model->brushq1.lightmapupdateflags;
11312
11313         // update light styles on this submodel
11314         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11315         {
11316                 model_brush_lightstyleinfo_t *style;
11317                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11318                 {
11319                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11320                         {
11321                                 int *list = style->surfacelist;
11322                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11323                                 for (j = 0;j < style->numsurfaces;j++)
11324                                         update[list[j]] = true;
11325                         }
11326                 }
11327         }
11328
11329         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11330
11331         if (debug)
11332         {
11333                 R_DrawDebugModel();
11334                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11335                 return;
11336         }
11337
11338         rsurface.lightmaptexture = NULL;
11339         rsurface.deluxemaptexture = NULL;
11340         rsurface.uselightmaptexture = false;
11341         rsurface.texture = NULL;
11342         rsurface.rtlight = NULL;
11343         numsurfacelist = 0;
11344         // add visible surfaces to draw list
11345         for (i = 0;i < model->nummodelsurfaces;i++)
11346         {
11347                 j = model->sortedmodelsurfaces[i];
11348                 if (r_refdef.viewcache.world_surfacevisible[j])
11349                         r_surfacelist[numsurfacelist++] = surfaces + j;
11350         }
11351         // update lightmaps if needed
11352         if (model->brushq1.firstrender)
11353         {
11354                 model->brushq1.firstrender = false;
11355                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11356                         if (update[j])
11357                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11358         }
11359         else if (update)
11360         {
11361                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11362                         if (r_refdef.viewcache.world_surfacevisible[j])
11363                                 if (update[j])
11364                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11365         }
11366         // don't do anything if there were no surfaces
11367         if (!numsurfacelist)
11368         {
11369                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11370                 return;
11371         }
11372         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11373
11374         // add to stats if desired
11375         if (r_speeds.integer && !skysurfaces && !depthonly)
11376         {
11377                 r_refdef.stats.world_surfaces += numsurfacelist;
11378                 for (j = 0;j < numsurfacelist;j++)
11379                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11380         }
11381
11382         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11383 }
11384
11385 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11386 {
11387         int i, j, endj, flagsmask;
11388         dp_model_t *model = ent->model;
11389         msurface_t *surfaces;
11390         unsigned char *update;
11391         int numsurfacelist = 0;
11392         if (model == NULL)
11393                 return;
11394
11395         if (r_maxsurfacelist < model->num_surfaces)
11396         {
11397                 r_maxsurfacelist = model->num_surfaces;
11398                 if (r_surfacelist)
11399                         Mem_Free((msurface_t **)r_surfacelist);
11400                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11401         }
11402
11403         // if the model is static it doesn't matter what value we give for
11404         // wantnormals and wanttangents, so this logic uses only rules applicable
11405         // to a model, knowing that they are meaningless otherwise
11406         if (ent == r_refdef.scene.worldentity)
11407                 RSurf_ActiveWorldEntity();
11408         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11409                 RSurf_ActiveModelEntity(ent, false, false, false);
11410         else if (prepass)
11411                 RSurf_ActiveModelEntity(ent, true, true, true);
11412         else if (depthonly)
11413         {
11414                 switch (vid.renderpath)
11415                 {
11416                 case RENDERPATH_GL20:
11417                 case RENDERPATH_D3D9:
11418                 case RENDERPATH_D3D10:
11419                 case RENDERPATH_D3D11:
11420                 case RENDERPATH_SOFT:
11421                 case RENDERPATH_GLES2:
11422                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11423                         break;
11424                 case RENDERPATH_GL11:
11425                 case RENDERPATH_GL13:
11426                 case RENDERPATH_GLES1:
11427                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11428                         break;
11429                 }
11430         }
11431         else
11432         {
11433                 switch (vid.renderpath)
11434                 {
11435                 case RENDERPATH_GL20:
11436                 case RENDERPATH_D3D9:
11437                 case RENDERPATH_D3D10:
11438                 case RENDERPATH_D3D11:
11439                 case RENDERPATH_SOFT:
11440                 case RENDERPATH_GLES2:
11441                         RSurf_ActiveModelEntity(ent, true, true, false);
11442                         break;
11443                 case RENDERPATH_GL11:
11444                 case RENDERPATH_GL13:
11445                 case RENDERPATH_GLES1:
11446                         RSurf_ActiveModelEntity(ent, true, false, false);
11447                         break;
11448                 }
11449         }
11450
11451         surfaces = model->data_surfaces;
11452         update = model->brushq1.lightmapupdateflags;
11453
11454         // update light styles
11455         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11456         {
11457                 model_brush_lightstyleinfo_t *style;
11458                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11459                 {
11460                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11461                         {
11462                                 int *list = style->surfacelist;
11463                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11464                                 for (j = 0;j < style->numsurfaces;j++)
11465                                         update[list[j]] = true;
11466                         }
11467                 }
11468         }
11469
11470         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11471
11472         if (debug)
11473         {
11474                 R_DrawDebugModel();
11475                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11476                 return;
11477         }
11478
11479         rsurface.lightmaptexture = NULL;
11480         rsurface.deluxemaptexture = NULL;
11481         rsurface.uselightmaptexture = false;
11482         rsurface.texture = NULL;
11483         rsurface.rtlight = NULL;
11484         numsurfacelist = 0;
11485         // add visible surfaces to draw list
11486         for (i = 0;i < model->nummodelsurfaces;i++)
11487                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11488         // don't do anything if there were no surfaces
11489         if (!numsurfacelist)
11490         {
11491                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11492                 return;
11493         }
11494         // update lightmaps if needed
11495         if (update)
11496         {
11497                 int updated = 0;
11498                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11499                 {
11500                         if (update[j])
11501                         {
11502                                 updated++;
11503                                 R_BuildLightMap(ent, surfaces + j);
11504                         }
11505                 }
11506         }
11507         if (update)
11508                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11509                         if (update[j])
11510                                 R_BuildLightMap(ent, surfaces + j);
11511         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11512
11513         // add to stats if desired
11514         if (r_speeds.integer && !skysurfaces && !depthonly)
11515         {
11516                 r_refdef.stats.entities_surfaces += numsurfacelist;
11517                 for (j = 0;j < numsurfacelist;j++)
11518                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11519         }
11520
11521         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11522 }
11523
11524 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11525 {
11526         static texture_t texture;
11527         static msurface_t surface;
11528         const msurface_t *surfacelist = &surface;
11529
11530         // fake enough texture and surface state to render this geometry
11531
11532         texture.update_lastrenderframe = -1; // regenerate this texture
11533         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11534         texture.currentskinframe = skinframe;
11535         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11536         texture.offsetmapping = OFFSETMAPPING_OFF;
11537         texture.offsetscale = 1;
11538         texture.specularscalemod = 1;
11539         texture.specularpowermod = 1;
11540
11541         surface.texture = &texture;
11542         surface.num_triangles = numtriangles;
11543         surface.num_firsttriangle = firsttriangle;
11544         surface.num_vertices = numvertices;
11545         surface.num_firstvertex = firstvertex;
11546
11547         // now render it
11548         rsurface.texture = R_GetCurrentTexture(surface.texture);
11549         rsurface.lightmaptexture = NULL;
11550         rsurface.deluxemaptexture = NULL;
11551         rsurface.uselightmaptexture = false;
11552         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11553 }
11554
11555 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)
11556 {
11557         static msurface_t surface;
11558         const msurface_t *surfacelist = &surface;
11559
11560         // fake enough texture and surface state to render this geometry
11561         surface.texture = texture;
11562         surface.num_triangles = numtriangles;
11563         surface.num_firsttriangle = firsttriangle;
11564         surface.num_vertices = numvertices;
11565         surface.num_firstvertex = firstvertex;
11566
11567         // now render it
11568         rsurface.texture = R_GetCurrentTexture(surface.texture);
11569         rsurface.lightmaptexture = NULL;
11570         rsurface.deluxemaptexture = NULL;
11571         rsurface.uselightmaptexture = false;
11572         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11573 }