]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
reworked use of alphatest - now only GL11/GL13/GLES1 paths use it, other
[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 when using vid_samples 2 or higher"};
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         {"#define USETRIPPY\n", " trippy"},
674 };
675
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
695 };
696
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 };
716
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
719 {
720         /// hash lookup data
721         struct r_glsl_permutation_s *hashnext;
722         unsigned int mode;
723         unsigned int permutation;
724
725         /// indicates if we have tried compiling this permutation already
726         qboolean compiled;
727         /// 0 if compilation failed
728         int program;
729         // texture units assigned to each detected uniform
730         int tex_Texture_First;
731         int tex_Texture_Second;
732         int tex_Texture_GammaRamps;
733         int tex_Texture_Normal;
734         int tex_Texture_Color;
735         int tex_Texture_Gloss;
736         int tex_Texture_Glow;
737         int tex_Texture_SecondaryNormal;
738         int tex_Texture_SecondaryColor;
739         int tex_Texture_SecondaryGloss;
740         int tex_Texture_SecondaryGlow;
741         int tex_Texture_Pants;
742         int tex_Texture_Shirt;
743         int tex_Texture_FogHeightTexture;
744         int tex_Texture_FogMask;
745         int tex_Texture_Lightmap;
746         int tex_Texture_Deluxemap;
747         int tex_Texture_Attenuation;
748         int tex_Texture_Cube;
749         int tex_Texture_Refraction;
750         int tex_Texture_Reflection;
751         int tex_Texture_ShadowMap2D;
752         int tex_Texture_CubeProjection;
753         int tex_Texture_ScreenDepth;
754         int tex_Texture_ScreenNormalMap;
755         int tex_Texture_ScreenDiffuse;
756         int tex_Texture_ScreenSpecular;
757         int tex_Texture_ReflectMask;
758         int tex_Texture_ReflectCube;
759         int tex_Texture_BounceGrid;
760         /// locations of detected uniforms in program object, or -1 if not found
761         int loc_Texture_First;
762         int loc_Texture_Second;
763         int loc_Texture_GammaRamps;
764         int loc_Texture_Normal;
765         int loc_Texture_Color;
766         int loc_Texture_Gloss;
767         int loc_Texture_Glow;
768         int loc_Texture_SecondaryNormal;
769         int loc_Texture_SecondaryColor;
770         int loc_Texture_SecondaryGloss;
771         int loc_Texture_SecondaryGlow;
772         int loc_Texture_Pants;
773         int loc_Texture_Shirt;
774         int loc_Texture_FogHeightTexture;
775         int loc_Texture_FogMask;
776         int loc_Texture_Lightmap;
777         int loc_Texture_Deluxemap;
778         int loc_Texture_Attenuation;
779         int loc_Texture_Cube;
780         int loc_Texture_Refraction;
781         int loc_Texture_Reflection;
782         int loc_Texture_ShadowMap2D;
783         int loc_Texture_CubeProjection;
784         int loc_Texture_ScreenDepth;
785         int loc_Texture_ScreenNormalMap;
786         int loc_Texture_ScreenDiffuse;
787         int loc_Texture_ScreenSpecular;
788         int loc_Texture_ReflectMask;
789         int loc_Texture_ReflectCube;
790         int loc_Texture_BounceGrid;
791         int loc_Alpha;
792         int loc_BloomBlur_Parameters;
793         int loc_ClientTime;
794         int loc_Color_Ambient;
795         int loc_Color_Diffuse;
796         int loc_Color_Specular;
797         int loc_Color_Glow;
798         int loc_Color_Pants;
799         int loc_Color_Shirt;
800         int loc_DeferredColor_Ambient;
801         int loc_DeferredColor_Diffuse;
802         int loc_DeferredColor_Specular;
803         int loc_DeferredMod_Diffuse;
804         int loc_DeferredMod_Specular;
805         int loc_DistortScaleRefractReflect;
806         int loc_EyePosition;
807         int loc_FogColor;
808         int loc_FogHeightFade;
809         int loc_FogPlane;
810         int loc_FogPlaneViewDist;
811         int loc_FogRangeRecip;
812         int loc_LightColor;
813         int loc_LightDir;
814         int loc_LightPosition;
815         int loc_OffsetMapping_ScaleSteps;
816         int loc_PixelSize;
817         int loc_ReflectColor;
818         int loc_ReflectFactor;
819         int loc_ReflectOffset;
820         int loc_RefractColor;
821         int loc_Saturation;
822         int loc_ScreenCenterRefractReflect;
823         int loc_ScreenScaleRefractReflect;
824         int loc_ScreenToDepth;
825         int loc_ShadowMap_Parameters;
826         int loc_ShadowMap_TextureScale;
827         int loc_SpecularPower;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 };
864 #define SHADERSTATICPARMS_COUNT 7
865
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
868
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
896 }
897
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901         else \
902                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 {
905         shaderstaticparms_count = 0;
906
907         // emit all
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
915 }
916
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
923
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 {
926         //unsigned int hashdepth = 0;
927         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928         r_glsl_permutation_t *p;
929         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930         {
931                 if (p->mode == mode && p->permutation == permutation)
932                 {
933                         //if (hashdepth > 10)
934                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935                         return p;
936                 }
937                 //hashdepth++;
938         }
939         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940         p->mode = mode;
941         p->permutation = permutation;
942         p->hashnext = r_glsl_permutationhash[mode][hashindex];
943         r_glsl_permutationhash[mode][hashindex] = p;
944         //if (hashdepth > 10)
945         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946         return p;
947 }
948
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
950 {
951         char *shaderstring;
952         if (!filename || !filename[0])
953                 return NULL;
954         if (!strcmp(filename, "glsl/default.glsl"))
955         {
956                 if (!glslshaderstring)
957                 {
958                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959                         if (glslshaderstring)
960                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
961                         else
962                                 glslshaderstring = (char *)builtinshaderstring;
963                 }
964                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
966                 return shaderstring;
967         }
968         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969         if (shaderstring)
970         {
971                 if (printfromdisknotice)
972                         Con_DPrintf("from disk %s... ", filename);
973                 return shaderstring;
974         }
975         return shaderstring;
976 }
977
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
979 {
980         int i;
981         int sampler;
982         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983         char *vertexstring, *geometrystring, *fragmentstring;
984         char permutationname[256];
985         int vertstrings_count = 0;
986         int geomstrings_count = 0;
987         int fragstrings_count = 0;
988         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991
992         if (p->compiled)
993                 return;
994         p->compiled = true;
995         p->program = 0;
996
997         permutationname[0] = 0;
998         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
999         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001
1002         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003
1004         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005         if(vid.support.gl20shaders130)
1006         {
1007                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1013         }
1014
1015         // the first pretext is which type of shader to compile as
1016         // (later these will all be bound together as a program object)
1017         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020
1021         // the second pretext is the mode (for example a light source)
1022         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026
1027         // now add all the permutation pretexts
1028         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029         {
1030                 if (permutation & (1<<i))
1031                 {
1032                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1036                 }
1037                 else
1038                 {
1039                         // keep line numbers correct
1040                         vertstrings_list[vertstrings_count++] = "\n";
1041                         geomstrings_list[geomstrings_count++] = "\n";
1042                         fragstrings_list[fragstrings_count++] = "\n";
1043                 }
1044         }
1045
1046         // add static parms
1047         R_CompileShader_AddStaticParms(mode, permutation);
1048         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049         vertstrings_count += shaderstaticparms_count;
1050         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051         geomstrings_count += shaderstaticparms_count;
1052         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053         fragstrings_count += shaderstaticparms_count;
1054
1055         // now append the shader text itself
1056         vertstrings_list[vertstrings_count++] = vertexstring;
1057         geomstrings_list[geomstrings_count++] = geometrystring;
1058         fragstrings_list[fragstrings_count++] = fragmentstring;
1059
1060         // if any sources were NULL, clear the respective list
1061         if (!vertexstring)
1062                 vertstrings_count = 0;
1063         if (!geometrystring)
1064                 geomstrings_count = 0;
1065         if (!fragmentstring)
1066                 fragstrings_count = 0;
1067
1068         // compile the shader program
1069         if (vertstrings_count + geomstrings_count + fragstrings_count)
1070                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1071         if (p->program)
1072         {
1073                 CHECKGLERROR
1074                 qglUseProgram(p->program);CHECKGLERROR
1075                 // look up all the uniform variable names we care about, so we don't
1076                 // have to look them up every time we set them
1077
1078                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1079                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1080                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1082                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1083                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1084                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1085                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1090                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1091                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1093                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1097                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1098                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1099                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1109                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1111                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1112                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1113                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1114                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1115                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1116                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1117                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1124                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1125                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1126                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1127                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1129                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1130                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1131                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1132                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1134                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1135                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1136                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1137                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1138                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1139                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1142                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1145                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1146                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1147                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1148                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1149                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1150                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1151                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1152                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1153                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163                 // initialize the samplers to refer to the texture units we use
1164                 p->tex_Texture_First = -1;
1165                 p->tex_Texture_Second = -1;
1166                 p->tex_Texture_GammaRamps = -1;
1167                 p->tex_Texture_Normal = -1;
1168                 p->tex_Texture_Color = -1;
1169                 p->tex_Texture_Gloss = -1;
1170                 p->tex_Texture_Glow = -1;
1171                 p->tex_Texture_SecondaryNormal = -1;
1172                 p->tex_Texture_SecondaryColor = -1;
1173                 p->tex_Texture_SecondaryGloss = -1;
1174                 p->tex_Texture_SecondaryGlow = -1;
1175                 p->tex_Texture_Pants = -1;
1176                 p->tex_Texture_Shirt = -1;
1177                 p->tex_Texture_FogHeightTexture = -1;
1178                 p->tex_Texture_FogMask = -1;
1179                 p->tex_Texture_Lightmap = -1;
1180                 p->tex_Texture_Deluxemap = -1;
1181                 p->tex_Texture_Attenuation = -1;
1182                 p->tex_Texture_Cube = -1;
1183                 p->tex_Texture_Refraction = -1;
1184                 p->tex_Texture_Reflection = -1;
1185                 p->tex_Texture_ShadowMap2D = -1;
1186                 p->tex_Texture_CubeProjection = -1;
1187                 p->tex_Texture_ScreenDepth = -1;
1188                 p->tex_Texture_ScreenNormalMap = -1;
1189                 p->tex_Texture_ScreenDiffuse = -1;
1190                 p->tex_Texture_ScreenSpecular = -1;
1191                 p->tex_Texture_ReflectMask = -1;
1192                 p->tex_Texture_ReflectCube = -1;
1193                 p->tex_Texture_BounceGrid = -1;
1194                 sampler = 0;
1195                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1196                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1197                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1198                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1199                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1200                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1201                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1206                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1207                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1208                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1210                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1211                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1212                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1213                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1214                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1215                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1216                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1217                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1224                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1225                 CHECKGLERROR
1226                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1227         }
1228         else
1229                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1230
1231         // free the strings
1232         if (vertexstring)
1233                 Mem_Free(vertexstring);
1234         if (geometrystring)
1235                 Mem_Free(geometrystring);
1236         if (fragmentstring)
1237                 Mem_Free(fragmentstring);
1238 }
1239
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 {
1242         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243         if (r_glsl_permutation != perm)
1244         {
1245                 r_glsl_permutation = perm;
1246                 if (!r_glsl_permutation->program)
1247                 {
1248                         if (!r_glsl_permutation->compiled)
1249                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1250                         if (!r_glsl_permutation->program)
1251                         {
1252                                 // remove features until we find a valid permutation
1253                                 int i;
1254                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255                                 {
1256                                         // reduce i more quickly whenever it would not remove any bits
1257                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258                                         if (!(permutation & j))
1259                                                 continue;
1260                                         permutation -= j;
1261                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262                                         if (!r_glsl_permutation->compiled)
1263                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1264                                         if (r_glsl_permutation->program)
1265                                                 break;
1266                                 }
1267                                 if (i >= SHADERPERMUTATION_COUNT)
1268                                 {
1269                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         qglUseProgram(0);CHECKGLERROR
1272                                         return; // no bit left to clear, entire mode is broken
1273                                 }
1274                         }
1275                 }
1276                 CHECKGLERROR
1277                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278         }
1279         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1282 }
1283
1284 #ifdef SUPPORTD3D
1285
1286 #ifdef SUPPORTD3D
1287 #include <d3d9.h>
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1290 #endif
1291
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1294 {
1295         /// hash lookup data
1296         struct r_hlsl_permutation_s *hashnext;
1297         unsigned int mode;
1298         unsigned int permutation;
1299
1300         /// indicates if we have tried compiling this permutation already
1301         qboolean compiled;
1302         /// NULL if compilation failed
1303         IDirect3DVertexShader9 *vertexshader;
1304         IDirect3DPixelShader9 *pixelshader;
1305 }
1306 r_hlsl_permutation_t;
1307
1308 typedef enum D3DVSREGISTER_e
1309 {
1310         D3DVSREGISTER_TexMatrix = 0, // float4x4
1311         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315         D3DVSREGISTER_ModelToLight = 20, // float4x4
1316         D3DVSREGISTER_EyePosition = 24,
1317         D3DVSREGISTER_FogPlane = 25,
1318         D3DVSREGISTER_LightDir = 26,
1319         D3DVSREGISTER_LightPosition = 27,
1320 }
1321 D3DVSREGISTER_t;
1322
1323 typedef enum D3DPSREGISTER_e
1324 {
1325         D3DPSREGISTER_Alpha = 0,
1326         D3DPSREGISTER_BloomBlur_Parameters = 1,
1327         D3DPSREGISTER_ClientTime = 2,
1328         D3DPSREGISTER_Color_Ambient = 3,
1329         D3DPSREGISTER_Color_Diffuse = 4,
1330         D3DPSREGISTER_Color_Specular = 5,
1331         D3DPSREGISTER_Color_Glow = 6,
1332         D3DPSREGISTER_Color_Pants = 7,
1333         D3DPSREGISTER_Color_Shirt = 8,
1334         D3DPSREGISTER_DeferredColor_Ambient = 9,
1335         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336         D3DPSREGISTER_DeferredColor_Specular = 11,
1337         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338         D3DPSREGISTER_DeferredMod_Specular = 13,
1339         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340         D3DPSREGISTER_EyePosition = 15, // unused
1341         D3DPSREGISTER_FogColor = 16,
1342         D3DPSREGISTER_FogHeightFade = 17,
1343         D3DPSREGISTER_FogPlane = 18,
1344         D3DPSREGISTER_FogPlaneViewDist = 19,
1345         D3DPSREGISTER_FogRangeRecip = 20,
1346         D3DPSREGISTER_LightColor = 21,
1347         D3DPSREGISTER_LightDir = 22, // unused
1348         D3DPSREGISTER_LightPosition = 23,
1349         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350         D3DPSREGISTER_PixelSize = 25,
1351         D3DPSREGISTER_ReflectColor = 26,
1352         D3DPSREGISTER_ReflectFactor = 27,
1353         D3DPSREGISTER_ReflectOffset = 28,
1354         D3DPSREGISTER_RefractColor = 29,
1355         D3DPSREGISTER_Saturation = 30,
1356         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358         D3DPSREGISTER_ScreenToDepth = 33,
1359         D3DPSREGISTER_ShadowMap_Parameters = 34,
1360         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361         D3DPSREGISTER_SpecularPower = 36,
1362         D3DPSREGISTER_UserVec1 = 37,
1363         D3DPSREGISTER_UserVec2 = 38,
1364         D3DPSREGISTER_UserVec3 = 39,
1365         D3DPSREGISTER_UserVec4 = 40,
1366         D3DPSREGISTER_ViewTintColor = 41,
1367         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368         D3DPSREGISTER_BloomColorSubtract = 43,
1369         D3DPSREGISTER_ViewToLight = 44, // float4x4
1370         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371         D3DPSREGISTER_NormalmapScrollBlend = 52,
1372         // next at 53
1373 }
1374 D3DPSREGISTER_t;
1375
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1382
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 {
1385         //unsigned int hashdepth = 0;
1386         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387         r_hlsl_permutation_t *p;
1388         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389         {
1390                 if (p->mode == mode && p->permutation == permutation)
1391                 {
1392                         //if (hashdepth > 10)
1393                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394                         return p;
1395                 }
1396                 //hashdepth++;
1397         }
1398         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399         p->mode = mode;
1400         p->permutation = permutation;
1401         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402         r_hlsl_permutationhash[mode][hashindex] = p;
1403         //if (hashdepth > 10)
1404         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405         return p;
1406 }
1407
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1409 {
1410         char *shaderstring;
1411         if (!filename || !filename[0])
1412                 return NULL;
1413         if (!strcmp(filename, "hlsl/default.hlsl"))
1414         {
1415                 if (!hlslshaderstring)
1416                 {
1417                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418                         if (hlslshaderstring)
1419                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420                         else
1421                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1422                 }
1423                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425                 return shaderstring;
1426         }
1427         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428         if (shaderstring)
1429         {
1430                 if (printfromdisknotice)
1431                         Con_DPrintf("from disk %s... ", filename);
1432                 return shaderstring;
1433         }
1434         return shaderstring;
1435 }
1436
1437 #include <d3dx9.h>
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1440
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 {
1443         DWORD *vsbin = NULL;
1444         DWORD *psbin = NULL;
1445         fs_offset_t vsbinsize;
1446         fs_offset_t psbinsize;
1447 //      IDirect3DVertexShader9 *vs = NULL;
1448 //      IDirect3DPixelShader9 *ps = NULL;
1449         ID3DXBuffer *vslog = NULL;
1450         ID3DXBuffer *vsbuffer = NULL;
1451         ID3DXConstantTable *vsconstanttable = NULL;
1452         ID3DXBuffer *pslog = NULL;
1453         ID3DXBuffer *psbuffer = NULL;
1454         ID3DXConstantTable *psconstanttable = NULL;
1455         int vsresult = 0;
1456         int psresult = 0;
1457         char temp[MAX_INPUTLINE];
1458         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459         qboolean debugshader = gl_paranoid.integer != 0;
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (!debugshader)
1463         {
1464                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466         }
1467         if ((!vsbin && vertstring) || (!psbin && fragstring))
1468         {
1469                 const char* dllnames_d3dx9 [] =
1470                 {
1471                         "d3dx9_43.dll",
1472                         "d3dx9_42.dll",
1473                         "d3dx9_41.dll",
1474                         "d3dx9_40.dll",
1475                         "d3dx9_39.dll",
1476                         "d3dx9_38.dll",
1477                         "d3dx9_37.dll",
1478                         "d3dx9_36.dll",
1479                         "d3dx9_35.dll",
1480                         "d3dx9_34.dll",
1481                         "d3dx9_33.dll",
1482                         "d3dx9_32.dll",
1483                         "d3dx9_31.dll",
1484                         "d3dx9_30.dll",
1485                         "d3dx9_29.dll",
1486                         "d3dx9_28.dll",
1487                         "d3dx9_27.dll",
1488                         "d3dx9_26.dll",
1489                         "d3dx9_25.dll",
1490                         "d3dx9_24.dll",
1491                         NULL
1492                 };
1493                 dllhandle_t d3dx9_dll = NULL;
1494                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497                 dllfunction_t d3dx9_dllfuncs[] =
1498                 {
1499                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1500                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1501                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1502                         {NULL, NULL}
1503                 };
1504                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505                 {
1506                         DWORD shaderflags = 0;
1507                         if (debugshader)
1508                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511                         if (vertstring && vertstring[0])
1512                         {
1513                                 if (debugshader)
1514                                 {
1515 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 }
1520                                 else
1521                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1522                                 if (vsbuffer)
1523                                 {
1524                                         vsbinsize = vsbuffer->GetBufferSize();
1525                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527                                         vsbuffer->Release();
1528                                 }
1529                                 if (vslog)
1530                                 {
1531                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1533                                         vslog->Release();
1534                                 }
1535                         }
1536                         if (fragstring && fragstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 }
1545                                 else
1546                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1547                                 if (psbuffer)
1548                                 {
1549                                         psbinsize = psbuffer->GetBufferSize();
1550                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552                                         psbuffer->Release();
1553                                 }
1554                                 if (pslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         pslog->Release();
1559                                 }
1560                         }
1561                         Sys_UnloadLibrary(&d3dx9_dll);
1562                 }
1563                 else
1564                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1565         }
1566         if (vsbin && psbin)
1567         {
1568                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569                 if (FAILED(vsresult))
1570                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572                 if (FAILED(psresult))
1573                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574         }
1575         // free the shader data
1576         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1578 }
1579
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1581 {
1582         int i;
1583         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584         int vertstring_length = 0;
1585         int geomstring_length = 0;
1586         int fragstring_length = 0;
1587         char *t;
1588         char *vertexstring, *geometrystring, *fragmentstring;
1589         char *vertstring, *geomstring, *fragstring;
1590         char permutationname[256];
1591         char cachename[256];
1592         int vertstrings_count = 0;
1593         int geomstrings_count = 0;
1594         int fragstrings_count = 0;
1595         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598
1599         if (p->compiled)
1600                 return;
1601         p->compiled = true;
1602         p->vertexshader = NULL;
1603         p->pixelshader = NULL;
1604
1605         permutationname[0] = 0;
1606         cachename[0] = 0;
1607         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610
1611         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612         strlcat(cachename, "hlsl/", sizeof(cachename));
1613
1614         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615         vertstrings_count = 0;
1616         geomstrings_count = 0;
1617         fragstrings_count = 0;
1618         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621
1622         // the first pretext is which type of shader to compile as
1623         // (later these will all be bound together as a program object)
1624         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627
1628         // the second pretext is the mode (for example a light source)
1629         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633         strlcat(cachename, modeinfo->name, sizeof(cachename));
1634
1635         // now add all the permutation pretexts
1636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637         {
1638                 if (permutation & (1<<i))
1639                 {
1640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1645                 }
1646                 else
1647                 {
1648                         // keep line numbers correct
1649                         vertstrings_list[vertstrings_count++] = "\n";
1650                         geomstrings_list[geomstrings_count++] = "\n";
1651                         fragstrings_list[fragstrings_count++] = "\n";
1652                 }
1653         }
1654
1655         // add static parms
1656         R_CompileShader_AddStaticParms(mode, permutation);
1657         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         vertstrings_count += shaderstaticparms_count;
1659         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         geomstrings_count += shaderstaticparms_count;
1661         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662         fragstrings_count += shaderstaticparms_count;
1663
1664         // replace spaces in the cachename with _ characters
1665         for (i = 0;cachename[i];i++)
1666                 if (cachename[i] == ' ')
1667                         cachename[i] = '_';
1668
1669         // now append the shader text itself
1670         vertstrings_list[vertstrings_count++] = vertexstring;
1671         geomstrings_list[geomstrings_count++] = geometrystring;
1672         fragstrings_list[fragstrings_count++] = fragmentstring;
1673
1674         // if any sources were NULL, clear the respective list
1675         if (!vertexstring)
1676                 vertstrings_count = 0;
1677         if (!geometrystring)
1678                 geomstrings_count = 0;
1679         if (!fragmentstring)
1680                 fragstrings_count = 0;
1681
1682         vertstring_length = 0;
1683         for (i = 0;i < vertstrings_count;i++)
1684                 vertstring_length += strlen(vertstrings_list[i]);
1685         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688
1689         geomstring_length = 0;
1690         for (i = 0;i < geomstrings_count;i++)
1691                 geomstring_length += strlen(geomstrings_list[i]);
1692         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695
1696         fragstring_length = 0;
1697         for (i = 0;i < fragstrings_count;i++)
1698                 fragstring_length += strlen(fragstrings_list[i]);
1699         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702
1703         // try to load the cached shader, or generate one
1704         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705
1706         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708         else
1709                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1710
1711         // free the strings
1712         if (vertstring)
1713                 Mem_Free(vertstring);
1714         if (geomstring)
1715                 Mem_Free(geomstring);
1716         if (fragstring)
1717                 Mem_Free(fragstring);
1718         if (vertexstring)
1719                 Mem_Free(vertexstring);
1720         if (geometrystring)
1721                 Mem_Free(geometrystring);
1722         if (fragmentstring)
1723                 Mem_Free(fragmentstring);
1724 }
1725
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 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);}
1729 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);}
1730 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);}
1731 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);}
1732
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1739
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 {
1742         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743         if (r_hlsl_permutation != perm)
1744         {
1745                 r_hlsl_permutation = perm;
1746                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                 {
1748                         if (!r_hlsl_permutation->compiled)
1749                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1750                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751                         {
1752                                 // remove features until we find a valid permutation
1753                                 int i;
1754                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755                                 {
1756                                         // reduce i more quickly whenever it would not remove any bits
1757                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758                                         if (!(permutation & j))
1759                                                 continue;
1760                                         permutation -= j;
1761                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762                                         if (!r_hlsl_permutation->compiled)
1763                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1764                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1765                                                 break;
1766                                 }
1767                                 if (i >= SHADERPERMUTATION_COUNT)
1768                                 {
1769                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         return; // no bit left to clear, entire mode is broken
1772                                 }
1773                         }
1774                 }
1775                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777         }
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1781 }
1782 #endif
1783
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 {
1786         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1790 }
1791
1792 void R_GLSL_Restart_f(void)
1793 {
1794         unsigned int i, limit;
1795         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796                 Mem_Free(glslshaderstring);
1797         glslshaderstring = NULL;
1798         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799                 Mem_Free(hlslshaderstring);
1800         hlslshaderstring = NULL;
1801         switch(vid.renderpath)
1802         {
1803         case RENDERPATH_D3D9:
1804 #ifdef SUPPORTD3D
1805                 {
1806                         r_hlsl_permutation_t *p;
1807                         r_hlsl_permutation = NULL;
1808                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809                         for (i = 0;i < limit;i++)
1810                         {
1811                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812                                 {
1813                                         if (p->vertexshader)
1814                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1815                                         if (p->pixelshader)
1816                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1817                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1818                                 }
1819                         }
1820                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1821                 }
1822 #endif
1823                 break;
1824         case RENDERPATH_D3D10:
1825                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_D3D11:
1828                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829                 break;
1830         case RENDERPATH_GL20:
1831         case RENDERPATH_GLES2:
1832                 {
1833                         r_glsl_permutation_t *p;
1834                         r_glsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839                                 {
1840                                         GL_Backend_FreeProgram(p->program);
1841                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1845                 }
1846                 break;
1847         case RENDERPATH_GL11:
1848         case RENDERPATH_GL13:
1849         case RENDERPATH_GLES1:
1850                 break;
1851         case RENDERPATH_SOFT:
1852                 break;
1853         }
1854 }
1855
1856 void R_GLSL_DumpShader_f(void)
1857 {
1858         int i;
1859         qfile_t *file;
1860
1861         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862         if (file)
1863         {
1864                 FS_Print(file, "/* The engine may define the following macros:\n");
1865                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866                 for (i = 0;i < SHADERMODE_COUNT;i++)
1867                         FS_Print(file, glslshadermodeinfo[i].pretext);
1868                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869                         FS_Print(file, shaderpermutationinfo[i].pretext);
1870                 FS_Print(file, "*/\n");
1871                 FS_Print(file, builtinshaderstring);
1872                 FS_Close(file);
1873                 Con_Printf("glsl/default.glsl written\n");
1874         }
1875         else
1876                 Con_Printf("failed to write to glsl/default.glsl\n");
1877
1878         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879         if (file)
1880         {
1881                 FS_Print(file, "/* The engine may define the following macros:\n");
1882                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883                 for (i = 0;i < SHADERMODE_COUNT;i++)
1884                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1885                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886                         FS_Print(file, shaderpermutationinfo[i].pretext);
1887                 FS_Print(file, "*/\n");
1888                 FS_Print(file, builtinhlslshaderstring);
1889                 FS_Close(file);
1890                 Con_Printf("hlsl/default.hlsl written\n");
1891         }
1892         else
1893                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 }
1895
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1897 {
1898         unsigned int permutation = 0;
1899         if (r_trippy.integer && !notrippy)
1900                 permutation |= SHADERPERMUTATION_TRIPPY;
1901         permutation |= SHADERPERMUTATION_VIEWTINT;
1902         if (first)
1903                 permutation |= SHADERPERMUTATION_DIFFUSE;
1904         if (second)
1905                 permutation |= SHADERPERMUTATION_SPECULAR;
1906         if (texturemode == GL_MODULATE)
1907                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908         else if (texturemode == GL_ADD)
1909                 permutation |= SHADERPERMUTATION_GLOW;
1910         else if (texturemode == GL_DECAL)
1911                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1912         if (!second)
1913                 texturemode = GL_MODULATE;
1914         GL_AlphaToCoverage(false);
1915         switch (vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1920                 R_Mesh_TexBind(GL20TU_FIRST , first );
1921                 R_Mesh_TexBind(GL20TU_SECOND, second);
1922 #endif
1923                 break;
1924         case RENDERPATH_D3D10:
1925                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926                 break;
1927         case RENDERPATH_D3D11:
1928                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929                 break;
1930         case RENDERPATH_GL20:
1931         case RENDERPATH_GLES2:
1932                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1933                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1934                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1935                 break;
1936         case RENDERPATH_GL13:
1937         case RENDERPATH_GLES1:
1938                 R_Mesh_TexBind(0, first );
1939                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1940                 R_Mesh_TexBind(1, second);
1941                 if (second)
1942                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1943                 break;
1944         case RENDERPATH_GL11:
1945                 R_Mesh_TexBind(0, first );
1946                 break;
1947         case RENDERPATH_SOFT:
1948                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1949                 R_Mesh_TexBind(GL20TU_FIRST , first );
1950                 R_Mesh_TexBind(GL20TU_SECOND, second);
1951                 break;
1952         }
1953 }
1954
1955 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1956 {
1957         unsigned int permutation = 0;
1958         if (r_trippy.integer && !notrippy)
1959                 permutation |= SHADERPERMUTATION_TRIPPY;
1960         GL_AlphaToCoverage(false);
1961         switch (vid.renderpath)
1962         {
1963         case RENDERPATH_D3D9:
1964 #ifdef SUPPORTD3D
1965                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1966 #endif
1967                 break;
1968         case RENDERPATH_D3D10:
1969                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1970                 break;
1971         case RENDERPATH_D3D11:
1972                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_GL20:
1975         case RENDERPATH_GLES2:
1976                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1977                 break;
1978         case RENDERPATH_GL13:
1979         case RENDERPATH_GLES1:
1980                 R_Mesh_TexBind(0, 0);
1981                 R_Mesh_TexBind(1, 0);
1982                 break;
1983         case RENDERPATH_GL11:
1984                 R_Mesh_TexBind(0, 0);
1985                 break;
1986         case RENDERPATH_SOFT:
1987                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1988                 break;
1989         }
1990 }
1991
1992 void R_SetupShader_ShowDepth(qboolean notrippy)
1993 {
1994         int permutation = 0;
1995         if (r_trippy.integer && !notrippy)
1996                 permutation |= SHADERPERMUTATION_TRIPPY;
1997         if (r_trippy.integer)
1998                 permutation |= SHADERPERMUTATION_TRIPPY;
1999         GL_AlphaToCoverage(false);
2000         switch (vid.renderpath)
2001         {
2002         case RENDERPATH_D3D9:
2003 #ifdef SUPPORTHLSL
2004                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2005 #endif
2006                 break;
2007         case RENDERPATH_D3D10:
2008                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_D3D11:
2011                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_GL20:
2014         case RENDERPATH_GLES2:
2015                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2016                 break;
2017         case RENDERPATH_GL13:
2018         case RENDERPATH_GLES1:
2019                 break;
2020         case RENDERPATH_GL11:
2021                 break;
2022         case RENDERPATH_SOFT:
2023                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2024                 break;
2025         }
2026 }
2027
2028 extern qboolean r_shadow_usingdeferredprepass;
2029 extern cvar_t r_shadow_deferred_8bitrange;
2030 extern rtexture_t *r_shadow_attenuationgradienttexture;
2031 extern rtexture_t *r_shadow_attenuation2dtexture;
2032 extern rtexture_t *r_shadow_attenuation3dtexture;
2033 extern qboolean r_shadow_usingshadowmap2d;
2034 extern qboolean r_shadow_usingshadowmaportho;
2035 extern float r_shadow_shadowmap_texturescale[2];
2036 extern float r_shadow_shadowmap_parameters[4];
2037 extern qboolean r_shadow_shadowmapvsdct;
2038 extern qboolean r_shadow_shadowmapsampler;
2039 extern int r_shadow_shadowmappcf;
2040 extern rtexture_t *r_shadow_shadowmap2dtexture;
2041 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2042 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2043 extern matrix4x4_t r_shadow_shadowmapmatrix;
2044 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2045 extern int r_shadow_prepass_width;
2046 extern int r_shadow_prepass_height;
2047 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2048 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2049 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2050 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2051 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2052
2053 #define BLENDFUNC_ALLOWS_COLORMOD      1
2054 #define BLENDFUNC_ALLOWS_FOG           2
2055 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2056 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2057 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2058 static int R_BlendFuncFlags(int src, int dst)
2059 {
2060         int r = 0;
2061
2062         // a blendfunc allows colormod if:
2063         // a) it can never keep the destination pixel invariant, or
2064         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2065         // this is to prevent unintended side effects from colormod
2066
2067         // a blendfunc allows fog if:
2068         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2069         // this is to prevent unintended side effects from fog
2070
2071         // these checks are the output of fogeval.pl
2072
2073         r |= BLENDFUNC_ALLOWS_COLORMOD;
2074         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2075         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2076         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2078         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2082         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2083         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2085         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095
2096         return r;
2097 }
2098
2099 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2100 {
2101         // select a permutation of the lighting shader appropriate to this
2102         // combination of texture, entity, light source, and fogging, only use the
2103         // minimum features necessary to avoid wasting rendering time in the
2104         // fragment shader on features that are not being used
2105         unsigned int permutation = 0;
2106         unsigned int mode = 0;
2107         int blendfuncflags;
2108         static float dummy_colormod[3] = {1, 1, 1};
2109         float *colormod = rsurface.colormod;
2110         float m16f[16];
2111         matrix4x4_t tempmatrix;
2112         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2113         if (r_trippy.integer && !notrippy)
2114                 permutation |= SHADERPERMUTATION_TRIPPY;
2115         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2116                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2117         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2118                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2119         if (rsurfacepass == RSURFPASS_BACKGROUND)
2120         {
2121                 // distorted background
2122                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2123                 {
2124                         mode = SHADERMODE_WATER;
2125                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2126                         {
2127                                 // this is the right thing to do for wateralpha
2128                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2129                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2130                         }
2131                         else
2132                         {
2133                                 // this is the right thing to do for entity alpha
2134                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2135                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2136                         }
2137                 }
2138                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2139                 {
2140                         mode = SHADERMODE_REFRACTION;
2141                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2142                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2143                 }
2144                 else
2145                 {
2146                         mode = SHADERMODE_GENERIC;
2147                         permutation |= SHADERPERMUTATION_DIFFUSE;
2148                         GL_BlendFunc(GL_ONE, GL_ZERO);
2149                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150                 }
2151                 GL_AlphaToCoverage(false);
2152         }
2153         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2154         {
2155                 if (r_glsl_offsetmapping.integer)
2156                 {
2157                         switch(rsurface.texture->offsetmapping)
2158                         {
2159                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2160                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2161                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2162                         case OFFSETMAPPING_OFF: break;
2163                         }
2164                 }
2165                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2166                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2167                 // normalmap (deferred prepass), may use alpha test on diffuse
2168                 mode = SHADERMODE_DEFERREDGEOMETRY;
2169                 GL_BlendFunc(GL_ONE, GL_ZERO);
2170                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2171                 GL_AlphaToCoverage(false);
2172         }
2173         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2174         {
2175                 if (r_glsl_offsetmapping.integer)
2176                 {
2177                         switch(rsurface.texture->offsetmapping)
2178                         {
2179                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2180                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2182                         case OFFSETMAPPING_OFF: break;
2183                         }
2184                 }
2185                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2187                 // light source
2188                 mode = SHADERMODE_LIGHTSOURCE;
2189                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2190                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2191                 if (diffusescale > 0)
2192                         permutation |= SHADERPERMUTATION_DIFFUSE;
2193                 if (specularscale > 0)
2194                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2195                 if (r_refdef.fogenabled)
2196                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2197                 if (rsurface.texture->colormapping)
2198                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2199                 if (r_shadow_usingshadowmap2d)
2200                 {
2201                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2202                         if(r_shadow_shadowmapvsdct)
2203                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2204
2205                         if (r_shadow_shadowmapsampler)
2206                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2207                         if (r_shadow_shadowmappcf > 1)
2208                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2209                         else if (r_shadow_shadowmappcf)
2210                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2211                 }
2212                 if (rsurface.texture->reflectmasktexture)
2213                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2214                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2215                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2216                 GL_AlphaToCoverage(false);
2217         }
2218         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2219         {
2220                 if (r_glsl_offsetmapping.integer)
2221                 {
2222                         switch(rsurface.texture->offsetmapping)
2223                         {
2224                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2225                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2226                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2227                         case OFFSETMAPPING_OFF: break;
2228                         }
2229                 }
2230                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2231                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2232                 // unshaded geometry (fullbright or ambient model lighting)
2233                 mode = SHADERMODE_FLATCOLOR;
2234                 ambientscale = diffusescale = specularscale = 0;
2235                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2236                         permutation |= SHADERPERMUTATION_GLOW;
2237                 if (r_refdef.fogenabled)
2238                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2239                 if (rsurface.texture->colormapping)
2240                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2241                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2242                 {
2243                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2244                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2245
2246                         if (r_shadow_shadowmapsampler)
2247                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2248                         if (r_shadow_shadowmappcf > 1)
2249                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2250                         else if (r_shadow_shadowmappcf)
2251                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2252                 }
2253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2254                         permutation |= SHADERPERMUTATION_REFLECTION;
2255                 if (rsurface.texture->reflectmasktexture)
2256                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2257                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2258                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2259                 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2260         }
2261         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2262         {
2263                 if (r_glsl_offsetmapping.integer)
2264                 {
2265                         switch(rsurface.texture->offsetmapping)
2266                         {
2267                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2268                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270                         case OFFSETMAPPING_OFF: break;
2271                         }
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275                 // directional model lighting
2276                 mode = SHADERMODE_LIGHTDIRECTION;
2277                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278                         permutation |= SHADERPERMUTATION_GLOW;
2279                 permutation |= SHADERPERMUTATION_DIFFUSE;
2280                 if (specularscale > 0)
2281                         permutation |= SHADERPERMUTATION_SPECULAR;
2282                 if (r_refdef.fogenabled)
2283                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2284                 if (rsurface.texture->colormapping)
2285                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2286                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2287                 {
2288                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2289                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2290
2291                         if (r_shadow_shadowmapsampler)
2292                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2293                         if (r_shadow_shadowmappcf > 1)
2294                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2295                         else if (r_shadow_shadowmappcf)
2296                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2299                         permutation |= SHADERPERMUTATION_REFLECTION;
2300                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2301                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2302                 if (rsurface.texture->reflectmasktexture)
2303                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304                 if (r_shadow_bouncegridtexture)
2305                 {
2306                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2307                         if (r_shadow_bouncegriddirectional)
2308                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2309                 }
2310                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2311                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2312                 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2313         }
2314         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2315         {
2316                 if (r_glsl_offsetmapping.integer)
2317                 {
2318                         switch(rsurface.texture->offsetmapping)
2319                         {
2320                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323                         case OFFSETMAPPING_OFF: break;
2324                         }
2325                 }
2326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328                 // ambient model lighting
2329                 mode = SHADERMODE_LIGHTDIRECTION;
2330                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331                         permutation |= SHADERPERMUTATION_GLOW;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmapsampler)
2342                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2343                         if (r_shadow_shadowmappcf > 1)
2344                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2345                         else if (r_shadow_shadowmappcf)
2346                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2349                         permutation |= SHADERPERMUTATION_REFLECTION;
2350                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2351                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2352                 if (rsurface.texture->reflectmasktexture)
2353                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2354                 if (r_shadow_bouncegridtexture)
2355                 {
2356                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2357                         if (r_shadow_bouncegriddirectional)
2358                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2359                 }
2360                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2361                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2362                 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2363         }
2364         else
2365         {
2366                 if (r_glsl_offsetmapping.integer)
2367                 {
2368                         switch(rsurface.texture->offsetmapping)
2369                         {
2370                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2371                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2372                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373                         case OFFSETMAPPING_OFF: break;
2374                         }
2375                 }
2376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2377                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2378                 // lightmapped wall
2379                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2380                         permutation |= SHADERPERMUTATION_GLOW;
2381                 if (r_refdef.fogenabled)
2382                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2383                 if (rsurface.texture->colormapping)
2384                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2385                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2386                 {
2387                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2388                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2389
2390                         if (r_shadow_shadowmapsampler)
2391                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2392                         if (r_shadow_shadowmappcf > 1)
2393                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2394                         else if (r_shadow_shadowmappcf)
2395                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2396                 }
2397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398                         permutation |= SHADERPERMUTATION_REFLECTION;
2399                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401                 if (rsurface.texture->reflectmasktexture)
2402                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403                 if (FAKELIGHT_ENABLED)
2404                 {
2405                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2406                         mode = SHADERMODE_FAKELIGHT;
2407                         permutation |= SHADERPERMUTATION_DIFFUSE;
2408                         if (specularscale > 0)
2409                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2410                 }
2411                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2412                 {
2413                         // deluxemapping (light direction texture)
2414                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2415                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2416                         else
2417                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2418                         permutation |= SHADERPERMUTATION_DIFFUSE;
2419                         if (specularscale > 0)
2420                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2421                 }
2422                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2423                 {
2424                         // fake deluxemapping (uniform light direction in tangentspace)
2425                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2426                         permutation |= SHADERPERMUTATION_DIFFUSE;
2427                         if (specularscale > 0)
2428                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2429                 }
2430                 else if (rsurface.uselightmaptexture)
2431                 {
2432                         // ordinary lightmapping (q1bsp, q3bsp)
2433                         mode = SHADERMODE_LIGHTMAP;
2434                 }
2435                 else
2436                 {
2437                         // ordinary vertex coloring (q3bsp)
2438                         mode = SHADERMODE_VERTEXCOLOR;
2439                 }
2440                 if (r_shadow_bouncegridtexture)
2441                 {
2442                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2443                         if (r_shadow_bouncegriddirectional)
2444                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2445                 }
2446                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2447                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2448                 GL_AlphaToCoverage(r_transparent_alphatocoverage.integer && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
2449         }
2450         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2451                 colormod = dummy_colormod;
2452         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2453                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2454         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2455                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2456         switch(vid.renderpath)
2457         {
2458         case RENDERPATH_D3D9:
2459 #ifdef SUPPORTD3D
2460                 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);
2461                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2462                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2463                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2464                 if (mode == SHADERMODE_LIGHTSOURCE)
2465                 {
2466                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2467                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2468                 }
2469                 else
2470                 {
2471                         if (mode == SHADERMODE_LIGHTDIRECTION)
2472                         {
2473                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2474                         }
2475                 }
2476                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2477                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2478                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2479                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2480                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2481
2482                 if (mode == SHADERMODE_LIGHTSOURCE)
2483                 {
2484                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2485                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2486                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2487                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2488                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2489
2490                         // additive passes are only darkened by fog, not tinted
2491                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2492                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2493                 }
2494                 else
2495                 {
2496                         if (mode == SHADERMODE_FLATCOLOR)
2497                         {
2498                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2499                         }
2500                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2501                         {
2502                                 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]);
2503                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2504                                 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);
2505                                 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);
2506                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2507                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2508                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2509                         }
2510                         else
2511                         {
2512                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2513                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2514                                 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);
2515                                 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);
2516                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2517                         }
2518                         // additive passes are only darkened by fog, not tinted
2519                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2520                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2521                         else
2522                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2523                         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);
2524                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2525                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2526                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2527                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2528                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2529                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2530                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2531                         if (mode == SHADERMODE_WATER)
2532                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2533                 }
2534                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2535                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2536                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2537                 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));
2538                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2539                 if (rsurface.texture->pantstexture)
2540                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2541                 else
2542                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2543                 if (rsurface.texture->shirttexture)
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2545                 else
2546                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2547                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2548                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2549                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2550                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2551                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2552                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2553                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2554                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2555                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2556                         );
2557                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2558                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2559
2560                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2561                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2562                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2563                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2564                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2565                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2566                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2567                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2568                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2569                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2570                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2571                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2572                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2573                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2574                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2575                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2576                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2577                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2578                 {
2579                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2580                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2581                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2582                 }
2583                 else
2584                 {
2585                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2586                 }
2587 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2588 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2589                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2590                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2591                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2592                 {
2593                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2594                         if (rsurface.rtlight)
2595                         {
2596                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2597                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2598                         }
2599                 }
2600 #endif
2601                 break;
2602         case RENDERPATH_D3D10:
2603                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2604                 break;
2605         case RENDERPATH_D3D11:
2606                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2607                 break;
2608         case RENDERPATH_GL20:
2609         case RENDERPATH_GLES2:
2610                 if (!vid.useinterleavedarrays)
2611                 {
2612                         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);
2613                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2614                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2615                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2616                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2617                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2618                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2619                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2620                 }
2621                 else
2622                 {
2623                         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);
2624                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2625                 }
2626                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2627                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2628                 if (mode == SHADERMODE_LIGHTSOURCE)
2629                 {
2630                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2631                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2632                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2633                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2634                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2635                         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);
2636         
2637                         // additive passes are only darkened by fog, not tinted
2638                         if (r_glsl_permutation->loc_FogColor >= 0)
2639                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2640                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2641                 }
2642                 else
2643                 {
2644                         if (mode == SHADERMODE_FLATCOLOR)
2645                         {
2646                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2647                         }
2648                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2649                         {
2650                                 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]);
2651                                 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]);
2652                                 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);
2653                                 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);
2654                                 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);
2655                                 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]);
2656                                 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]);
2657                         }
2658                         else
2659                         {
2660                                 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]);
2661                                 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]);
2662                                 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);
2663                                 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);
2664                                 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);
2665                         }
2666                         // additive passes are only darkened by fog, not tinted
2667                         if (r_glsl_permutation->loc_FogColor >= 0)
2668                         {
2669                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2670                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2671                                 else
2672                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2673                         }
2674                         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);
2675                         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]);
2676                         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]);
2677                         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]);
2678                         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]);
2679                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2680                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2681                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2682                         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]);
2683                 }
2684                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2685                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2686                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2687                 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]);
2688                 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]);
2689
2690                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2691                 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));
2692                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2693                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2694                 {
2695                         if (rsurface.texture->pantstexture)
2696                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2697                         else
2698                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2699                 }
2700                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2701                 {
2702                         if (rsurface.texture->shirttexture)
2703                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2704                         else
2705                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2706                 }
2707                 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]);
2708                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2709                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2710                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2711                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2712                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2713                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2714                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2716                         );
2717                 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]);
2718                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2719                 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);}
2720                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2721
2722                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2723                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2724                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2725                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2726                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2727                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2728                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2729                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2730                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2731                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2732                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2733                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2734                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2735                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2736                 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);
2737                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2738                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2739                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2740                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2741                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2742                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2743                 {
2744                         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);
2745                         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);
2746                         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);
2747                 }
2748                 else
2749                 {
2750                         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);
2751                 }
2752                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2753                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2754                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2755                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2756                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2757                 {
2758                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2759                         if (rsurface.rtlight)
2760                         {
2761                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2762                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2763                         }
2764                 }
2765                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2766                 CHECKGLERROR
2767                 break;
2768         case RENDERPATH_GL11:
2769         case RENDERPATH_GL13:
2770         case RENDERPATH_GLES1:
2771                 break;
2772         case RENDERPATH_SOFT:
2773                 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);
2774                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2775                 R_SetupShader_SetPermutationSoft(mode, permutation);
2776                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2777                 if (mode == SHADERMODE_LIGHTSOURCE)
2778                 {
2779                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2780                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2781                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2782                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2783                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2784                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2785         
2786                         // additive passes are only darkened by fog, not tinted
2787                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2788                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2789                 }
2790                 else
2791                 {
2792                         if (mode == SHADERMODE_FLATCOLOR)
2793                         {
2794                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2795                         }
2796                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2797                         {
2798                                 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]);
2799                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2800                                 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);
2801                                 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);
2802                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2803                                 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]);
2804                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2805                         }
2806                         else
2807                         {
2808                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2809                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2810                                 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);
2811                                 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);
2812                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2813                         }
2814                         // additive passes are only darkened by fog, not tinted
2815                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2816                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2817                         else
2818                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2819                         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);
2820                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2821                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2822                         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]);
2823                         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]);
2824                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2825                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2826                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2827                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2828                 }
2829                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2830                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2831                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2832                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2833                 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]);
2834
2835                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2836                 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));
2837                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2838                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2839                 {
2840                         if (rsurface.texture->pantstexture)
2841                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2842                         else
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2844                 }
2845                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2846                 {
2847                         if (rsurface.texture->shirttexture)
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2849                         else
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2851                 }
2852                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2853                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2854                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2855                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2856                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2857                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2858                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2859                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2860                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2861                         );
2862                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2863                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2864
2865                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2866                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2867                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2868                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2869                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2870                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2871                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2872                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2873                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2874                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2875                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2876                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2877                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2878                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2879                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2880                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2881                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2882                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2883                 {
2884                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2885                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2886                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2887                 }
2888                 else
2889                 {
2890                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2891                 }
2892 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2893 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2894                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2895                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2896                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2897                 {
2898                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2899                         if (rsurface.rtlight)
2900                         {
2901                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2902                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2903                         }
2904                 }
2905                 break;
2906         }
2907 }
2908
2909 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2910 {
2911         // select a permutation of the lighting shader appropriate to this
2912         // combination of texture, entity, light source, and fogging, only use the
2913         // minimum features necessary to avoid wasting rendering time in the
2914         // fragment shader on features that are not being used
2915         unsigned int permutation = 0;
2916         unsigned int mode = 0;
2917         const float *lightcolorbase = rtlight->currentcolor;
2918         float ambientscale = rtlight->ambientscale;
2919         float diffusescale = rtlight->diffusescale;
2920         float specularscale = rtlight->specularscale;
2921         // this is the location of the light in view space
2922         vec3_t viewlightorigin;
2923         // this transforms from view space (camera) to light space (cubemap)
2924         matrix4x4_t viewtolight;
2925         matrix4x4_t lighttoview;
2926         float viewtolight16f[16];
2927         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2928         // light source
2929         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2930         if (rtlight->currentcubemap != r_texture_whitecube)
2931                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2932         if (diffusescale > 0)
2933                 permutation |= SHADERPERMUTATION_DIFFUSE;
2934         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2935                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2936         if (r_shadow_usingshadowmap2d)
2937         {
2938                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2939                 if (r_shadow_shadowmapvsdct)
2940                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2941
2942                 if (r_shadow_shadowmapsampler)
2943                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2944                 if (r_shadow_shadowmappcf > 1)
2945                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2946                 else if (r_shadow_shadowmappcf)
2947                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2948         }
2949         GL_AlphaToCoverage(false);
2950         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2951         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2952         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2953         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2954         switch(vid.renderpath)
2955         {
2956         case RENDERPATH_D3D9:
2957 #ifdef SUPPORTD3D
2958                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2959                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2961                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2962                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2963                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2966                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2967                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2969
2970                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2971                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2972                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2974                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2975                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2976 #endif
2977                 break;
2978         case RENDERPATH_D3D10:
2979                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2980                 break;
2981         case RENDERPATH_D3D11:
2982                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2983                 break;
2984         case RENDERPATH_GL20:
2985         case RENDERPATH_GLES2:
2986                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2987                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2988                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2989                 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);
2990                 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);
2991                 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);
2992                 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]);
2993                 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]);
2994                 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));
2995                 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]);
2996                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2997
2998                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2999                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3000                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3001                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3002                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3003                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3004                 break;
3005         case RENDERPATH_GL11:
3006         case RENDERPATH_GL13:
3007         case RENDERPATH_GLES1:
3008                 break;
3009         case RENDERPATH_SOFT:
3010                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3011                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3012                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3013                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3014                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3015                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3016                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3017                 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]);
3018                 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));
3019                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3020                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3021
3022                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3023                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3024                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3025                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3026                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3027                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3028                 break;
3029         }
3030 }
3031
3032 #define SKINFRAME_HASH 1024
3033
3034 typedef struct
3035 {
3036         int loadsequence; // incremented each level change
3037         memexpandablearray_t array;
3038         skinframe_t *hash[SKINFRAME_HASH];
3039 }
3040 r_skinframe_t;
3041 r_skinframe_t r_skinframe;
3042
3043 void R_SkinFrame_PrepareForPurge(void)
3044 {
3045         r_skinframe.loadsequence++;
3046         // wrap it without hitting zero
3047         if (r_skinframe.loadsequence >= 200)
3048                 r_skinframe.loadsequence = 1;
3049 }
3050
3051 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3052 {
3053         if (!skinframe)
3054                 return;
3055         // mark the skinframe as used for the purging code
3056         skinframe->loadsequence = r_skinframe.loadsequence;
3057 }
3058
3059 void R_SkinFrame_Purge(void)
3060 {
3061         int i;
3062         skinframe_t *s;
3063         for (i = 0;i < SKINFRAME_HASH;i++)
3064         {
3065                 for (s = r_skinframe.hash[i];s;s = s->next)
3066                 {
3067                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3068                         {
3069                                 if (s->merged == s->base)
3070                                         s->merged = NULL;
3071                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3072                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3073                                 R_PurgeTexture(s->merged);s->merged = NULL;
3074                                 R_PurgeTexture(s->base  );s->base   = NULL;
3075                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3076                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3077                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3078                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3079                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3080                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3081                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3082                                 s->loadsequence = 0;
3083                         }
3084                 }
3085         }
3086 }
3087
3088 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3089         skinframe_t *item;
3090         char basename[MAX_QPATH];
3091
3092         Image_StripImageExtension(name, basename, sizeof(basename));
3093
3094         if( last == NULL ) {
3095                 int hashindex;
3096                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3097                 item = r_skinframe.hash[hashindex];
3098         } else {
3099                 item = last->next;
3100         }
3101
3102         // linearly search through the hash bucket
3103         for( ; item ; item = item->next ) {
3104                 if( !strcmp( item->basename, basename ) ) {
3105                         return item;
3106                 }
3107         }
3108         return NULL;
3109 }
3110
3111 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3112 {
3113         skinframe_t *item;
3114         int hashindex;
3115         char basename[MAX_QPATH];
3116
3117         Image_StripImageExtension(name, basename, sizeof(basename));
3118
3119         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3120         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3121                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3122                         break;
3123
3124         if (!item) {
3125                 rtexture_t *dyntexture;
3126                 // check whether its a dynamic texture
3127                 dyntexture = CL_GetDynTexture( basename );
3128                 if (!add && !dyntexture)
3129                         return NULL;
3130                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3131                 memset(item, 0, sizeof(*item));
3132                 strlcpy(item->basename, basename, sizeof(item->basename));
3133                 item->base = dyntexture; // either NULL or dyntexture handle
3134                 item->textureflags = textureflags;
3135                 item->comparewidth = comparewidth;
3136                 item->compareheight = compareheight;
3137                 item->comparecrc = comparecrc;
3138                 item->next = r_skinframe.hash[hashindex];
3139                 r_skinframe.hash[hashindex] = item;
3140         }
3141         else if( item->base == NULL )
3142         {
3143                 rtexture_t *dyntexture;
3144                 // check whether its a dynamic texture
3145                 // 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]
3146                 dyntexture = CL_GetDynTexture( basename );
3147                 item->base = dyntexture; // either NULL or dyntexture handle
3148         }
3149
3150         R_SkinFrame_MarkUsed(item);
3151         return item;
3152 }
3153
3154 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3155         { \
3156                 unsigned long long avgcolor[5], wsum; \
3157                 int pix, comp, w; \
3158                 avgcolor[0] = 0; \
3159                 avgcolor[1] = 0; \
3160                 avgcolor[2] = 0; \
3161                 avgcolor[3] = 0; \
3162                 avgcolor[4] = 0; \
3163                 wsum = 0; \
3164                 for(pix = 0; pix < cnt; ++pix) \
3165                 { \
3166                         w = 0; \
3167                         for(comp = 0; comp < 3; ++comp) \
3168                                 w += getpixel; \
3169                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3170                         { \
3171                                 ++wsum; \
3172                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3173                                 w = getpixel; \
3174                                 for(comp = 0; comp < 3; ++comp) \
3175                                         avgcolor[comp] += getpixel * w; \
3176                                 avgcolor[3] += w; \
3177                         } \
3178                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3179                         avgcolor[4] += getpixel; \
3180                 } \
3181                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3182                         avgcolor[3] = 1; \
3183                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3184                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3185                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3186                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3187         }
3188
3189 extern cvar_t gl_picmip;
3190 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3191 {
3192         int j;
3193         unsigned char *pixels;
3194         unsigned char *bumppixels;
3195         unsigned char *basepixels = NULL;
3196         int basepixels_width = 0;
3197         int basepixels_height = 0;
3198         skinframe_t *skinframe;
3199         rtexture_t *ddsbase = NULL;
3200         qboolean ddshasalpha = false;
3201         float ddsavgcolor[4];
3202         char basename[MAX_QPATH];
3203         int miplevel = R_PicmipForFlags(textureflags);
3204         int savemiplevel = miplevel;
3205         int mymiplevel;
3206
3207         if (cls.state == ca_dedicated)
3208                 return NULL;
3209
3210         // return an existing skinframe if already loaded
3211         // if loading of the first image fails, don't make a new skinframe as it
3212         // would cause all future lookups of this to be missing
3213         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3214         if (skinframe && skinframe->base)
3215                 return skinframe;
3216
3217         Image_StripImageExtension(name, basename, sizeof(basename));
3218
3219         // check for DDS texture file first
3220         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3221         {
3222                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3223                 if (basepixels == NULL)
3224                         return NULL;
3225         }
3226
3227         // FIXME handle miplevel
3228
3229         if (developer_loading.integer)
3230                 Con_Printf("loading skin \"%s\"\n", name);
3231
3232         // we've got some pixels to store, so really allocate this new texture now
3233         if (!skinframe)
3234                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3235         skinframe->stain = NULL;
3236         skinframe->merged = NULL;
3237         skinframe->base = NULL;
3238         skinframe->pants = NULL;
3239         skinframe->shirt = NULL;
3240         skinframe->nmap = NULL;
3241         skinframe->gloss = NULL;
3242         skinframe->glow = NULL;
3243         skinframe->fog = NULL;
3244         skinframe->reflect = NULL;
3245         skinframe->hasalpha = false;
3246
3247         if (ddsbase)
3248         {
3249                 skinframe->base = ddsbase;
3250                 skinframe->hasalpha = ddshasalpha;
3251                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3252                 if (r_loadfog && skinframe->hasalpha)
3253                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3254                 //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]);
3255         }
3256         else
3257         {
3258                 basepixels_width = image_width;
3259                 basepixels_height = image_height;
3260                 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);
3261                 if (textureflags & TEXF_ALPHA)
3262                 {
3263                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3264                         {
3265                                 if (basepixels[j] < 255)
3266                                 {
3267                                         skinframe->hasalpha = true;
3268                                         break;
3269                                 }
3270                         }
3271                         if (r_loadfog && skinframe->hasalpha)
3272                         {
3273                                 // has transparent pixels
3274                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3275                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3276                                 {
3277                                         pixels[j+0] = 255;
3278                                         pixels[j+1] = 255;
3279                                         pixels[j+2] = 255;
3280                                         pixels[j+3] = basepixels[j+3];
3281                                 }
3282                                 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);
3283                                 Mem_Free(pixels);
3284                         }
3285                 }
3286                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3287                 //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]);
3288                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3289                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3290                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3291                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3292         }
3293
3294         if (r_loaddds)
3295         {
3296                 mymiplevel = savemiplevel;
3297                 if (r_loadnormalmap)
3298                         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);
3299                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3300                 if (r_loadgloss)
3301                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3302                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3303                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3304                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3305         }
3306
3307         // _norm is the name used by tenebrae and has been adopted as standard
3308         if (r_loadnormalmap && skinframe->nmap == NULL)
3309         {
3310                 mymiplevel = savemiplevel;
3311                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3312                 {
3313                         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);
3314                         Mem_Free(pixels);
3315                         pixels = NULL;
3316                 }
3317                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3318                 {
3319                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3320                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3321                         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);
3322                         Mem_Free(pixels);
3323                         Mem_Free(bumppixels);
3324                 }
3325                 else if (r_shadow_bumpscale_basetexture.value > 0)
3326                 {
3327                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3328                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3329                         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);
3330                         Mem_Free(pixels);
3331                 }
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3333                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3334         }
3335
3336         // _luma is supported only for tenebrae compatibility
3337         // _glow is the preferred name
3338         mymiplevel = savemiplevel;
3339         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))))
3340         {
3341                 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);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3343                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3344                 Mem_Free(pixels);pixels = NULL;
3345         }
3346
3347         mymiplevel = savemiplevel;
3348         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3349         {
3350                 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);
3351                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3352                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3353                 Mem_Free(pixels);
3354                 pixels = NULL;
3355         }
3356
3357         mymiplevel = savemiplevel;
3358         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3359         {
3360                 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);
3361                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3362                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3363                 Mem_Free(pixels);
3364                 pixels = NULL;
3365         }
3366
3367         mymiplevel = savemiplevel;
3368         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3369         {
3370                 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);
3371                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3372                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3373                 Mem_Free(pixels);
3374                 pixels = NULL;
3375         }
3376
3377         mymiplevel = savemiplevel;
3378         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3379         {
3380                 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);
3381                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3382                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3383                 Mem_Free(pixels);
3384                 pixels = NULL;
3385         }
3386
3387         if (basepixels)
3388                 Mem_Free(basepixels);
3389
3390         return skinframe;
3391 }
3392
3393 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3394 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3395 {
3396         int i;
3397         unsigned char *temp1, *temp2;
3398         skinframe_t *skinframe;
3399
3400         if (cls.state == ca_dedicated)
3401                 return NULL;
3402
3403         // if already loaded just return it, otherwise make a new skinframe
3404         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3405         if (skinframe && skinframe->base)
3406                 return skinframe;
3407
3408         skinframe->stain = NULL;
3409         skinframe->merged = NULL;
3410         skinframe->base = NULL;
3411         skinframe->pants = NULL;
3412         skinframe->shirt = NULL;
3413         skinframe->nmap = NULL;
3414         skinframe->gloss = NULL;
3415         skinframe->glow = NULL;
3416         skinframe->fog = NULL;
3417         skinframe->reflect = NULL;
3418         skinframe->hasalpha = false;
3419
3420         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3421         if (!skindata)
3422                 return NULL;
3423
3424         if (developer_loading.integer)
3425                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3426
3427         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3428         {
3429                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3430                 temp2 = temp1 + width * height * 4;
3431                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3432                 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);
3433                 Mem_Free(temp1);
3434         }
3435         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3436         if (textureflags & TEXF_ALPHA)
3437         {
3438                 for (i = 3;i < width * height * 4;i += 4)
3439                 {
3440                         if (skindata[i] < 255)
3441                         {
3442                                 skinframe->hasalpha = true;
3443                                 break;
3444                         }
3445                 }
3446                 if (r_loadfog && skinframe->hasalpha)
3447                 {
3448                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3449                         memcpy(fogpixels, skindata, width * height * 4);
3450                         for (i = 0;i < width * height * 4;i += 4)
3451                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3452                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3453                         Mem_Free(fogpixels);
3454                 }
3455         }
3456
3457         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3458         //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]);
3459
3460         return skinframe;
3461 }
3462
3463 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3464 {
3465         int i;
3466         int featuresmask;
3467         skinframe_t *skinframe;
3468
3469         if (cls.state == ca_dedicated)
3470                 return NULL;
3471
3472         // if already loaded just return it, otherwise make a new skinframe
3473         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3474         if (skinframe && skinframe->base)
3475                 return skinframe;
3476
3477         skinframe->stain = NULL;
3478         skinframe->merged = NULL;
3479         skinframe->base = NULL;
3480         skinframe->pants = NULL;
3481         skinframe->shirt = NULL;
3482         skinframe->nmap = NULL;
3483         skinframe->gloss = NULL;
3484         skinframe->glow = NULL;
3485         skinframe->fog = NULL;
3486         skinframe->reflect = NULL;
3487         skinframe->hasalpha = false;
3488
3489         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3490         if (!skindata)
3491                 return NULL;
3492
3493         if (developer_loading.integer)
3494                 Con_Printf("loading quake skin \"%s\"\n", name);
3495
3496         // 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)
3497         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3498         memcpy(skinframe->qpixels, skindata, width*height);
3499         skinframe->qwidth = width;
3500         skinframe->qheight = height;
3501
3502         featuresmask = 0;
3503         for (i = 0;i < width * height;i++)
3504                 featuresmask |= palette_featureflags[skindata[i]];
3505
3506         skinframe->hasalpha = false;
3507         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3508         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3509         skinframe->qgeneratemerged = true;
3510         skinframe->qgeneratebase = skinframe->qhascolormapping;
3511         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3512
3513         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3514         //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]);
3515
3516         return skinframe;
3517 }
3518
3519 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3520 {
3521         int width;
3522         int height;
3523         unsigned char *skindata;
3524
3525         if (!skinframe->qpixels)
3526                 return;
3527
3528         if (!skinframe->qhascolormapping)
3529                 colormapped = false;
3530
3531         if (colormapped)
3532         {
3533                 if (!skinframe->qgeneratebase)
3534                         return;
3535         }
3536         else
3537         {
3538                 if (!skinframe->qgeneratemerged)
3539                         return;
3540         }
3541
3542         width = skinframe->qwidth;
3543         height = skinframe->qheight;
3544         skindata = skinframe->qpixels;
3545
3546         if (skinframe->qgeneratenmap)
3547         {
3548                 unsigned char *temp1, *temp2;
3549                 skinframe->qgeneratenmap = false;
3550                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3551                 temp2 = temp1 + width * height * 4;
3552                 // use either a custom palette or the quake palette
3553                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3554                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3555                 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);
3556                 Mem_Free(temp1);
3557         }
3558
3559         if (skinframe->qgenerateglow)
3560         {
3561                 skinframe->qgenerateglow = false;
3562                 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
3563         }
3564
3565         if (colormapped)
3566         {
3567                 skinframe->qgeneratebase = false;
3568                 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);
3569                 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);
3570                 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);
3571         }
3572         else
3573         {
3574                 skinframe->qgeneratemerged = false;
3575                 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);
3576         }
3577
3578         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3579         {
3580                 Mem_Free(skinframe->qpixels);
3581                 skinframe->qpixels = NULL;
3582         }
3583 }
3584
3585 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)
3586 {
3587         int i;
3588         skinframe_t *skinframe;
3589
3590         if (cls.state == ca_dedicated)
3591                 return NULL;
3592
3593         // if already loaded just return it, otherwise make a new skinframe
3594         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3595         if (skinframe && skinframe->base)
3596                 return skinframe;
3597
3598         skinframe->stain = NULL;
3599         skinframe->merged = NULL;
3600         skinframe->base = NULL;
3601         skinframe->pants = NULL;
3602         skinframe->shirt = NULL;
3603         skinframe->nmap = NULL;
3604         skinframe->gloss = NULL;
3605         skinframe->glow = NULL;
3606         skinframe->fog = NULL;
3607         skinframe->reflect = NULL;
3608         skinframe->hasalpha = false;
3609
3610         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3611         if (!skindata)
3612                 return NULL;
3613
3614         if (developer_loading.integer)
3615                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3616
3617         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3618         if (textureflags & TEXF_ALPHA)
3619         {
3620                 for (i = 0;i < width * height;i++)
3621                 {
3622                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3623                         {
3624                                 skinframe->hasalpha = true;
3625                                 break;
3626                         }
3627                 }
3628                 if (r_loadfog && skinframe->hasalpha)
3629                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3630         }
3631
3632         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3633         //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]);
3634
3635         return skinframe;
3636 }
3637
3638 skinframe_t *R_SkinFrame_LoadMissing(void)
3639 {
3640         skinframe_t *skinframe;
3641
3642         if (cls.state == ca_dedicated)
3643                 return NULL;
3644
3645         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3646         skinframe->stain = NULL;
3647         skinframe->merged = NULL;
3648         skinframe->base = NULL;
3649         skinframe->pants = NULL;
3650         skinframe->shirt = NULL;
3651         skinframe->nmap = NULL;
3652         skinframe->gloss = NULL;
3653         skinframe->glow = NULL;
3654         skinframe->fog = NULL;
3655         skinframe->reflect = NULL;
3656         skinframe->hasalpha = false;
3657
3658         skinframe->avgcolor[0] = rand() / RAND_MAX;
3659         skinframe->avgcolor[1] = rand() / RAND_MAX;
3660         skinframe->avgcolor[2] = rand() / RAND_MAX;
3661         skinframe->avgcolor[3] = 1;
3662
3663         return skinframe;
3664 }
3665
3666 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3667 typedef struct suffixinfo_s
3668 {
3669         const char *suffix;
3670         qboolean flipx, flipy, flipdiagonal;
3671 }
3672 suffixinfo_t;
3673 static suffixinfo_t suffix[3][6] =
3674 {
3675         {
3676                 {"px",   false, false, false},
3677                 {"nx",   false, false, false},
3678                 {"py",   false, false, false},
3679                 {"ny",   false, false, false},
3680                 {"pz",   false, false, false},
3681                 {"nz",   false, false, false}
3682         },
3683         {
3684                 {"posx", false, false, false},
3685                 {"negx", false, false, false},
3686                 {"posy", false, false, false},
3687                 {"negy", false, false, false},
3688                 {"posz", false, false, false},
3689                 {"negz", false, false, false}
3690         },
3691         {
3692                 {"rt",    true, false,  true},
3693                 {"lf",   false,  true,  true},
3694                 {"ft",    true,  true, false},
3695                 {"bk",   false, false, false},
3696                 {"up",    true, false,  true},
3697                 {"dn",    true, false,  true}
3698         }
3699 };
3700
3701 static int componentorder[4] = {0, 1, 2, 3};
3702
3703 rtexture_t *R_LoadCubemap(const char *basename)
3704 {
3705         int i, j, cubemapsize;
3706         unsigned char *cubemappixels, *image_buffer;
3707         rtexture_t *cubemaptexture;
3708         char name[256];
3709         // must start 0 so the first loadimagepixels has no requested width/height
3710         cubemapsize = 0;
3711         cubemappixels = NULL;
3712         cubemaptexture = NULL;
3713         // keep trying different suffix groups (posx, px, rt) until one loads
3714         for (j = 0;j < 3 && !cubemappixels;j++)
3715         {
3716                 // load the 6 images in the suffix group
3717                 for (i = 0;i < 6;i++)
3718                 {
3719                         // generate an image name based on the base and and suffix
3720                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3721                         // load it
3722                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3723                         {
3724                                 // an image loaded, make sure width and height are equal
3725                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3726                                 {
3727                                         // if this is the first image to load successfully, allocate the cubemap memory
3728                                         if (!cubemappixels && image_width >= 1)
3729                                         {
3730                                                 cubemapsize = image_width;
3731                                                 // note this clears to black, so unavailable sides are black
3732                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3733                                         }
3734                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3735                                         if (cubemappixels)
3736                                                 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);
3737                                 }
3738                                 else
3739                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3740                                 // free the image
3741                                 Mem_Free(image_buffer);
3742                         }
3743                 }
3744         }
3745         // if a cubemap loaded, upload it
3746         if (cubemappixels)
3747         {
3748                 if (developer_loading.integer)
3749                         Con_Printf("loading cubemap \"%s\"\n", basename);
3750
3751                 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);
3752                 Mem_Free(cubemappixels);
3753         }
3754         else
3755         {
3756                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3757                 if (developer_loading.integer)
3758                 {
3759                         Con_Printf("(tried tried images ");
3760                         for (j = 0;j < 3;j++)
3761                                 for (i = 0;i < 6;i++)
3762                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3763                         Con_Print(" and was unable to find any of them).\n");
3764                 }
3765         }
3766         return cubemaptexture;
3767 }
3768
3769 rtexture_t *R_GetCubemap(const char *basename)
3770 {
3771         int i;
3772         for (i = 0;i < r_texture_numcubemaps;i++)
3773                 if (r_texture_cubemaps[i] != NULL)
3774                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3775                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3776         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3777                 return r_texture_whitecube;
3778         r_texture_numcubemaps++;
3779         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3780         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3781         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3782         return r_texture_cubemaps[i]->texture;
3783 }
3784
3785 void R_FreeCubemap(const char *basename)
3786 {
3787         int i;
3788
3789         for (i = 0;i < r_texture_numcubemaps;i++)
3790         {
3791                 if (r_texture_cubemaps[i] != NULL)
3792                 {
3793                         if (r_texture_cubemaps[i]->texture)
3794                         {
3795                                 if (developer_loading.integer)
3796                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3797                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3798                                 Mem_Free(r_texture_cubemaps[i]);
3799                                 r_texture_cubemaps[i] = NULL;
3800                         }
3801                 }
3802         }
3803 }
3804
3805 void R_FreeCubemaps(void)
3806 {
3807         int i;
3808         for (i = 0;i < r_texture_numcubemaps;i++)
3809         {
3810                 if (developer_loading.integer)
3811                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3812                 if (r_texture_cubemaps[i] != NULL)
3813                 {
3814                         if (r_texture_cubemaps[i]->texture)
3815                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3816                         Mem_Free(r_texture_cubemaps[i]);
3817                 }
3818         }
3819         r_texture_numcubemaps = 0;
3820 }
3821
3822 void R_Main_FreeViewCache(void)
3823 {
3824         if (r_refdef.viewcache.entityvisible)
3825                 Mem_Free(r_refdef.viewcache.entityvisible);
3826         if (r_refdef.viewcache.world_pvsbits)
3827                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3828         if (r_refdef.viewcache.world_leafvisible)
3829                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3830         if (r_refdef.viewcache.world_surfacevisible)
3831                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3832         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3833 }
3834
3835 void R_Main_ResizeViewCache(void)
3836 {
3837         int numentities = r_refdef.scene.numentities;
3838         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3839         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3840         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3841         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3842         if (r_refdef.viewcache.maxentities < numentities)
3843         {
3844                 r_refdef.viewcache.maxentities = numentities;
3845                 if (r_refdef.viewcache.entityvisible)
3846                         Mem_Free(r_refdef.viewcache.entityvisible);
3847                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3848         }
3849         if (r_refdef.viewcache.world_numclusters != numclusters)
3850         {
3851                 r_refdef.viewcache.world_numclusters = numclusters;
3852                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3853                 if (r_refdef.viewcache.world_pvsbits)
3854                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3855                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3856         }
3857         if (r_refdef.viewcache.world_numleafs != numleafs)
3858         {
3859                 r_refdef.viewcache.world_numleafs = numleafs;
3860                 if (r_refdef.viewcache.world_leafvisible)
3861                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3862                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3863         }
3864         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3865         {
3866                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3867                 if (r_refdef.viewcache.world_surfacevisible)
3868                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3869                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3870         }
3871 }
3872
3873 extern rtexture_t *loadingscreentexture;
3874 void gl_main_start(void)
3875 {
3876         loadingscreentexture = NULL;
3877         r_texture_blanknormalmap = NULL;
3878         r_texture_white = NULL;
3879         r_texture_grey128 = NULL;
3880         r_texture_black = NULL;
3881         r_texture_whitecube = NULL;
3882         r_texture_normalizationcube = NULL;
3883         r_texture_fogattenuation = NULL;
3884         r_texture_fogheighttexture = NULL;
3885         r_texture_gammaramps = NULL;
3886         r_texture_numcubemaps = 0;
3887
3888         r_loaddds = r_texture_dds_load.integer != 0;
3889         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3890
3891         switch(vid.renderpath)
3892         {
3893         case RENDERPATH_GL20:
3894         case RENDERPATH_D3D9:
3895         case RENDERPATH_D3D10:
3896         case RENDERPATH_D3D11:
3897         case RENDERPATH_SOFT:
3898         case RENDERPATH_GLES2:
3899                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3900                 Cvar_SetValueQuick(&gl_combine, 1);
3901                 Cvar_SetValueQuick(&r_glsl, 1);
3902                 r_loadnormalmap = true;
3903                 r_loadgloss = true;
3904                 r_loadfog = false;
3905                 break;
3906         case RENDERPATH_GL13:
3907         case RENDERPATH_GLES1:
3908                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3909                 Cvar_SetValueQuick(&gl_combine, 1);
3910                 Cvar_SetValueQuick(&r_glsl, 0);
3911                 r_loadnormalmap = false;
3912                 r_loadgloss = false;
3913                 r_loadfog = true;
3914                 break;
3915         case RENDERPATH_GL11:
3916                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3917                 Cvar_SetValueQuick(&gl_combine, 0);
3918                 Cvar_SetValueQuick(&r_glsl, 0);
3919                 r_loadnormalmap = false;
3920                 r_loadgloss = false;
3921                 r_loadfog = true;
3922                 break;
3923         }
3924
3925         R_AnimCache_Free();
3926         R_FrameData_Reset();
3927
3928         r_numqueries = 0;
3929         r_maxqueries = 0;
3930         memset(r_queries, 0, sizeof(r_queries));
3931
3932         r_qwskincache = NULL;
3933         r_qwskincache_size = 0;
3934
3935         // due to caching of texture_t references, the collision cache must be reset
3936         Collision_Cache_Reset(true);
3937
3938         // set up r_skinframe loading system for textures
3939         memset(&r_skinframe, 0, sizeof(r_skinframe));
3940         r_skinframe.loadsequence = 1;
3941         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3942
3943         r_main_texturepool = R_AllocTexturePool();
3944         R_BuildBlankTextures();
3945         R_BuildNoTexture();
3946         if (vid.support.arb_texture_cube_map)
3947         {
3948                 R_BuildWhiteCube();
3949                 R_BuildNormalizationCube();
3950         }
3951         r_texture_fogattenuation = NULL;
3952         r_texture_fogheighttexture = NULL;
3953         r_texture_gammaramps = NULL;
3954         //r_texture_fogintensity = NULL;
3955         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3956         memset(&r_waterstate, 0, sizeof(r_waterstate));
3957         r_glsl_permutation = NULL;
3958         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3959         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3960         glslshaderstring = NULL;
3961 #ifdef SUPPORTD3D
3962         r_hlsl_permutation = NULL;
3963         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3964         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3965 #endif
3966         hlslshaderstring = NULL;
3967         memset(&r_svbsp, 0, sizeof (r_svbsp));
3968
3969         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3970         r_texture_numcubemaps = 0;
3971
3972         r_refdef.fogmasktable_density = 0;
3973 }
3974
3975 void gl_main_shutdown(void)
3976 {
3977         R_AnimCache_Free();
3978         R_FrameData_Reset();
3979
3980         R_Main_FreeViewCache();
3981
3982         switch(vid.renderpath)
3983         {
3984         case RENDERPATH_GL11:
3985         case RENDERPATH_GL13:
3986         case RENDERPATH_GL20:
3987         case RENDERPATH_GLES1:
3988         case RENDERPATH_GLES2:
3989                 if (r_maxqueries)
3990                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3991                 break;
3992         case RENDERPATH_D3D9:
3993                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3994                 break;
3995         case RENDERPATH_D3D10:
3996                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3997                 break;
3998         case RENDERPATH_D3D11:
3999                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4000                 break;
4001         case RENDERPATH_SOFT:
4002                 break;
4003         }
4004
4005         r_numqueries = 0;
4006         r_maxqueries = 0;
4007         memset(r_queries, 0, sizeof(r_queries));
4008
4009         r_qwskincache = NULL;
4010         r_qwskincache_size = 0;
4011
4012         // clear out the r_skinframe state
4013         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4014         memset(&r_skinframe, 0, sizeof(r_skinframe));
4015
4016         if (r_svbsp.nodes)
4017                 Mem_Free(r_svbsp.nodes);
4018         memset(&r_svbsp, 0, sizeof (r_svbsp));
4019         R_FreeTexturePool(&r_main_texturepool);
4020         loadingscreentexture = NULL;
4021         r_texture_blanknormalmap = NULL;
4022         r_texture_white = NULL;
4023         r_texture_grey128 = NULL;
4024         r_texture_black = NULL;
4025         r_texture_whitecube = NULL;
4026         r_texture_normalizationcube = NULL;
4027         r_texture_fogattenuation = NULL;
4028         r_texture_fogheighttexture = NULL;
4029         r_texture_gammaramps = NULL;
4030         r_texture_numcubemaps = 0;
4031         //r_texture_fogintensity = NULL;
4032         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4033         memset(&r_waterstate, 0, sizeof(r_waterstate));
4034         R_GLSL_Restart_f();
4035
4036         r_glsl_permutation = NULL;
4037         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4038         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4039         glslshaderstring = NULL;
4040 #ifdef SUPPORTD3D
4041         r_hlsl_permutation = NULL;
4042         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4043         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4044 #endif
4045         hlslshaderstring = NULL;
4046 }
4047
4048 extern void CL_ParseEntityLump(char *entitystring);
4049 void gl_main_newmap(void)
4050 {
4051         // FIXME: move this code to client
4052         char *entities, entname[MAX_QPATH];
4053         if (r_qwskincache)
4054                 Mem_Free(r_qwskincache);
4055         r_qwskincache = NULL;
4056         r_qwskincache_size = 0;
4057         if (cl.worldmodel)
4058         {
4059                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4060                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4061                 {
4062                         CL_ParseEntityLump(entities);
4063                         Mem_Free(entities);
4064                         return;
4065                 }
4066                 if (cl.worldmodel->brush.entities)
4067                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4068         }
4069         R_Main_FreeViewCache();
4070
4071         R_FrameData_Reset();
4072 }
4073
4074 void GL_Main_Init(void)
4075 {
4076         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4077
4078         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4079         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4080         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4081         if (gamemode == GAME_NEHAHRA)
4082         {
4083                 Cvar_RegisterVariable (&gl_fogenable);
4084                 Cvar_RegisterVariable (&gl_fogdensity);
4085                 Cvar_RegisterVariable (&gl_fogred);
4086                 Cvar_RegisterVariable (&gl_foggreen);
4087                 Cvar_RegisterVariable (&gl_fogblue);
4088                 Cvar_RegisterVariable (&gl_fogstart);
4089                 Cvar_RegisterVariable (&gl_fogend);
4090                 Cvar_RegisterVariable (&gl_skyclip);
4091         }
4092         Cvar_RegisterVariable(&r_motionblur);
4093         Cvar_RegisterVariable(&r_motionblur_maxblur);
4094         Cvar_RegisterVariable(&r_motionblur_bmin);
4095         Cvar_RegisterVariable(&r_motionblur_vmin);
4096         Cvar_RegisterVariable(&r_motionblur_vmax);
4097         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4098         Cvar_RegisterVariable(&r_motionblur_randomize);
4099         Cvar_RegisterVariable(&r_damageblur);
4100         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4101         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4102         Cvar_RegisterVariable(&r_equalize_entities_by);
4103         Cvar_RegisterVariable(&r_equalize_entities_to);
4104         Cvar_RegisterVariable(&r_depthfirst);
4105         Cvar_RegisterVariable(&r_useinfinitefarclip);
4106         Cvar_RegisterVariable(&r_farclip_base);
4107         Cvar_RegisterVariable(&r_farclip_world);
4108         Cvar_RegisterVariable(&r_nearclip);
4109         Cvar_RegisterVariable(&r_deformvertexes);
4110         Cvar_RegisterVariable(&r_transparent);
4111         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4112         Cvar_RegisterVariable(&r_showoverdraw);
4113         Cvar_RegisterVariable(&r_showbboxes);
4114         Cvar_RegisterVariable(&r_showsurfaces);
4115         Cvar_RegisterVariable(&r_showtris);
4116         Cvar_RegisterVariable(&r_shownormals);
4117         Cvar_RegisterVariable(&r_showlighting);
4118         Cvar_RegisterVariable(&r_showshadowvolumes);
4119         Cvar_RegisterVariable(&r_showcollisionbrushes);
4120         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4121         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4122         Cvar_RegisterVariable(&r_showdisabledepthtest);
4123         Cvar_RegisterVariable(&r_drawportals);
4124         Cvar_RegisterVariable(&r_drawentities);
4125         Cvar_RegisterVariable(&r_draw2d);
4126         Cvar_RegisterVariable(&r_drawworld);
4127         Cvar_RegisterVariable(&r_cullentities_trace);
4128         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4129         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4130         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4131         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4132         Cvar_RegisterVariable(&r_drawviewmodel);
4133         Cvar_RegisterVariable(&r_drawexteriormodel);
4134         Cvar_RegisterVariable(&r_speeds);
4135         Cvar_RegisterVariable(&r_fullbrights);
4136         Cvar_RegisterVariable(&r_wateralpha);
4137         Cvar_RegisterVariable(&r_dynamic);
4138         Cvar_RegisterVariable(&r_fakelight);
4139         Cvar_RegisterVariable(&r_fakelight_intensity);
4140         Cvar_RegisterVariable(&r_fullbright);
4141         Cvar_RegisterVariable(&r_shadows);
4142         Cvar_RegisterVariable(&r_shadows_darken);
4143         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4144         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4145         Cvar_RegisterVariable(&r_shadows_throwdistance);
4146         Cvar_RegisterVariable(&r_shadows_throwdirection);
4147         Cvar_RegisterVariable(&r_shadows_focus);
4148         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4149         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4150         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4151         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4152         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4153         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4154         Cvar_RegisterVariable(&r_fog_exp2);
4155         Cvar_RegisterVariable(&r_fog_clear);
4156         Cvar_RegisterVariable(&r_drawfog);
4157         Cvar_RegisterVariable(&r_transparentdepthmasking);
4158         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4159         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4160         Cvar_RegisterVariable(&r_texture_dds_load);
4161         Cvar_RegisterVariable(&r_texture_dds_save);
4162         Cvar_RegisterVariable(&r_textureunits);
4163         Cvar_RegisterVariable(&gl_combine);
4164         Cvar_RegisterVariable(&r_viewfbo);
4165         Cvar_RegisterVariable(&r_viewscale);
4166         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4167         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4168         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4169         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4170         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4171         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4172         Cvar_RegisterVariable(&r_glsl);
4173         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4174         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4175         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4176         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4177         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4178         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4179         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4180         Cvar_RegisterVariable(&r_glsl_postprocess);
4181         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4182         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4183         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4184         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4185         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4186         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4187         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4188         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4189
4190         Cvar_RegisterVariable(&r_water);
4191         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4192         Cvar_RegisterVariable(&r_water_clippingplanebias);
4193         Cvar_RegisterVariable(&r_water_refractdistort);
4194         Cvar_RegisterVariable(&r_water_reflectdistort);
4195         Cvar_RegisterVariable(&r_water_scissormode);
4196         Cvar_RegisterVariable(&r_water_lowquality);
4197
4198         Cvar_RegisterVariable(&r_lerpsprites);
4199         Cvar_RegisterVariable(&r_lerpmodels);
4200         Cvar_RegisterVariable(&r_lerplightstyles);
4201         Cvar_RegisterVariable(&r_waterscroll);
4202         Cvar_RegisterVariable(&r_bloom);
4203         Cvar_RegisterVariable(&r_bloom_colorscale);
4204         Cvar_RegisterVariable(&r_bloom_brighten);
4205         Cvar_RegisterVariable(&r_bloom_blur);
4206         Cvar_RegisterVariable(&r_bloom_resolution);
4207         Cvar_RegisterVariable(&r_bloom_colorexponent);
4208         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4209         Cvar_RegisterVariable(&r_hdr);
4210         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4211         Cvar_RegisterVariable(&r_hdr_glowintensity);
4212         Cvar_RegisterVariable(&r_hdr_range);
4213         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4214         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4215         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4216         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4217         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4218         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4219         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4220         Cvar_RegisterVariable(&developer_texturelogging);
4221         Cvar_RegisterVariable(&gl_lightmaps);
4222         Cvar_RegisterVariable(&r_test);
4223         Cvar_RegisterVariable(&r_glsl_saturation);
4224         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4225         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4226         Cvar_RegisterVariable(&r_framedatasize);
4227         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4228                 Cvar_SetValue("r_fullbrights", 0);
4229         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4230 }
4231
4232 extern void R_Textures_Init(void);
4233 extern void GL_Draw_Init(void);
4234 extern void GL_Main_Init(void);
4235 extern void R_Shadow_Init(void);
4236 extern void R_Sky_Init(void);
4237 extern void GL_Surf_Init(void);
4238 extern void R_Particles_Init(void);
4239 extern void R_Explosion_Init(void);
4240 extern void gl_backend_init(void);
4241 extern void Sbar_Init(void);
4242 extern void R_LightningBeams_Init(void);
4243 extern void Mod_RenderInit(void);
4244 extern void Font_Init(void);
4245
4246 void Render_Init(void)
4247 {
4248         gl_backend_init();
4249         R_Textures_Init();
4250         GL_Main_Init();
4251         Font_Init();
4252         GL_Draw_Init();
4253         R_Shadow_Init();
4254         R_Sky_Init();
4255         GL_Surf_Init();
4256         Sbar_Init();
4257         R_Particles_Init();
4258         R_Explosion_Init();
4259         R_LightningBeams_Init();
4260         Mod_RenderInit();
4261 }
4262
4263 /*
4264 ===============
4265 GL_Init
4266 ===============
4267 */
4268 extern char *ENGINE_EXTENSIONS;
4269 void GL_Init (void)
4270 {
4271         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4272         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4273         gl_version = (const char *)qglGetString(GL_VERSION);
4274         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4275
4276         if (!gl_extensions)
4277                 gl_extensions = "";
4278         if (!gl_platformextensions)
4279                 gl_platformextensions = "";
4280
4281         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4282         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4283         Con_Printf("GL_VERSION: %s\n", gl_version);
4284         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4285         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4286
4287         VID_CheckExtensions();
4288
4289         // LordHavoc: report supported extensions
4290         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4291
4292         // clear to black (loading plaque will be seen over this)
4293         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4294 }
4295
4296 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4297 {
4298         int i;
4299         mplane_t *p;
4300         if (r_trippy.integer)
4301                 return false;
4302         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4303         {
4304                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4305                 if (i == 4)
4306                         continue;
4307                 p = r_refdef.view.frustum + i;
4308                 switch(p->signbits)
4309                 {
4310                 default:
4311                 case 0:
4312                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4313                                 return true;
4314                         break;
4315                 case 1:
4316                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4317                                 return true;
4318                         break;
4319                 case 2:
4320                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4321                                 return true;
4322                         break;
4323                 case 3:
4324                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4325                                 return true;
4326                         break;
4327                 case 4:
4328                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4329                                 return true;
4330                         break;
4331                 case 5:
4332                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4333                                 return true;
4334                         break;
4335                 case 6:
4336                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4337                                 return true;
4338                         break;
4339                 case 7:
4340                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4341                                 return true;
4342                         break;
4343                 }
4344         }
4345         return false;
4346 }
4347
4348 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4349 {
4350         int i;
4351         const mplane_t *p;
4352         if (r_trippy.integer)
4353                 return false;
4354         for (i = 0;i < numplanes;i++)
4355         {
4356                 p = planes + i;
4357                 switch(p->signbits)
4358                 {
4359                 default:
4360                 case 0:
4361                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4362                                 return true;
4363                         break;
4364                 case 1:
4365                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4366                                 return true;
4367                         break;
4368                 case 2:
4369                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4370                                 return true;
4371                         break;
4372                 case 3:
4373                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4374                                 return true;
4375                         break;
4376                 case 4:
4377                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4378                                 return true;
4379                         break;
4380                 case 5:
4381                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 6:
4385                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 7:
4389                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 }
4393         }
4394         return false;
4395 }
4396
4397 //==================================================================================
4398
4399 // LordHavoc: this stores temporary data used within the same frame
4400
4401 typedef struct r_framedata_mem_s
4402 {
4403         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4404         size_t size; // how much usable space
4405         size_t current; // how much space in use
4406         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4407         size_t wantedsize; // how much space was allocated
4408         unsigned char *data; // start of real data (16byte aligned)
4409 }
4410 r_framedata_mem_t;
4411
4412 static r_framedata_mem_t *r_framedata_mem;
4413
4414 void R_FrameData_Reset(void)
4415 {
4416         while (r_framedata_mem)
4417         {
4418                 r_framedata_mem_t *next = r_framedata_mem->purge;
4419                 Mem_Free(r_framedata_mem);
4420                 r_framedata_mem = next;
4421         }
4422 }
4423
4424 void R_FrameData_Resize(void)
4425 {
4426         size_t wantedsize;
4427         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4428         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4429         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4430         {
4431                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4432                 newmem->wantedsize = wantedsize;
4433                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4434                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4435                 newmem->current = 0;
4436                 newmem->mark = 0;
4437                 newmem->purge = r_framedata_mem;
4438                 r_framedata_mem = newmem;
4439         }
4440 }
4441
4442 void R_FrameData_NewFrame(void)
4443 {
4444         R_FrameData_Resize();
4445         if (!r_framedata_mem)
4446                 return;
4447         // if we ran out of space on the last frame, free the old memory now
4448         while (r_framedata_mem->purge)
4449         {
4450                 // repeatedly remove the second item in the list, leaving only head
4451                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4452                 Mem_Free(r_framedata_mem->purge);
4453                 r_framedata_mem->purge = next;
4454         }
4455         // reset the current mem pointer
4456         r_framedata_mem->current = 0;
4457         r_framedata_mem->mark = 0;
4458 }
4459
4460 void *R_FrameData_Alloc(size_t size)
4461 {
4462         void *data;
4463
4464         // align to 16 byte boundary - the data pointer is already aligned, so we
4465         // only need to ensure the size of every allocation is also aligned
4466         size = (size + 15) & ~15;
4467
4468         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4469         {
4470                 // emergency - we ran out of space, allocate more memory
4471                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4472                 R_FrameData_Resize();
4473         }
4474
4475         data = r_framedata_mem->data + r_framedata_mem->current;
4476         r_framedata_mem->current += size;
4477
4478         // count the usage for stats
4479         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4480         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4481
4482         return (void *)data;
4483 }
4484
4485 void *R_FrameData_Store(size_t size, void *data)
4486 {
4487         void *d = R_FrameData_Alloc(size);
4488         if (d && data)
4489                 memcpy(d, data, size);
4490         return d;
4491 }
4492
4493 void R_FrameData_SetMark(void)
4494 {
4495         if (!r_framedata_mem)
4496                 return;
4497         r_framedata_mem->mark = r_framedata_mem->current;
4498 }
4499
4500 void R_FrameData_ReturnToMark(void)
4501 {
4502         if (!r_framedata_mem)
4503                 return;
4504         r_framedata_mem->current = r_framedata_mem->mark;
4505 }
4506
4507 //==================================================================================
4508
4509 // LordHavoc: animcache originally written by Echon, rewritten since then
4510
4511 /**
4512  * Animation cache prevents re-generating mesh data for an animated model
4513  * multiple times in one frame for lighting, shadowing, reflections, etc.
4514  */
4515
4516 void R_AnimCache_Free(void)
4517 {
4518 }
4519
4520 void R_AnimCache_ClearCache(void)
4521 {
4522         int i;
4523         entity_render_t *ent;
4524
4525         for (i = 0;i < r_refdef.scene.numentities;i++)
4526         {
4527                 ent = r_refdef.scene.entities[i];
4528                 ent->animcache_vertex3f = NULL;
4529                 ent->animcache_normal3f = NULL;
4530                 ent->animcache_svector3f = NULL;
4531                 ent->animcache_tvector3f = NULL;
4532                 ent->animcache_vertexmesh = NULL;
4533                 ent->animcache_vertex3fbuffer = NULL;
4534                 ent->animcache_vertexmeshbuffer = NULL;
4535         }
4536 }
4537
4538 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4539 {
4540         int i;
4541
4542         // check if we need the meshbuffers
4543         if (!vid.useinterleavedarrays)
4544                 return;
4545
4546         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4547                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4548         // TODO: upload vertex3f buffer?
4549         if (ent->animcache_vertexmesh)
4550         {
4551                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4552                 for (i = 0;i < numvertices;i++)
4553                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4554                 if (ent->animcache_svector3f)
4555                         for (i = 0;i < numvertices;i++)
4556                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4557                 if (ent->animcache_tvector3f)
4558                         for (i = 0;i < numvertices;i++)
4559                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4560                 if (ent->animcache_normal3f)
4561                         for (i = 0;i < numvertices;i++)
4562                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4563                 // TODO: upload vertexmeshbuffer?
4564         }
4565 }
4566
4567 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4568 {
4569         dp_model_t *model = ent->model;
4570         int numvertices;
4571         // see if it's already cached this frame
4572         if (ent->animcache_vertex3f)
4573         {
4574                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4575                 if (wantnormals || wanttangents)
4576                 {
4577                         if (ent->animcache_normal3f)
4578                                 wantnormals = false;
4579                         if (ent->animcache_svector3f)
4580                                 wanttangents = false;
4581                         if (wantnormals || wanttangents)
4582                         {
4583                                 numvertices = model->surfmesh.num_vertices;
4584                                 if (wantnormals)
4585                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4586                                 if (wanttangents)
4587                                 {
4588                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4589                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4590                                 }
4591                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4592                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4593                         }
4594                 }
4595         }
4596         else
4597         {
4598                 // see if this ent is worth caching
4599                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4600                         return false;
4601                 // get some memory for this entity and generate mesh data
4602                 numvertices = model->surfmesh.num_vertices;
4603                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4604                 if (wantnormals)
4605                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4606                 if (wanttangents)
4607                 {
4608                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4609                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4610                 }
4611                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4612                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4613         }
4614         return true;
4615 }
4616
4617 void R_AnimCache_CacheVisibleEntities(void)
4618 {
4619         int i;
4620         qboolean wantnormals = true;
4621         qboolean wanttangents = !r_showsurfaces.integer;
4622
4623         switch(vid.renderpath)
4624         {
4625         case RENDERPATH_GL20:
4626         case RENDERPATH_D3D9:
4627         case RENDERPATH_D3D10:
4628         case RENDERPATH_D3D11:
4629         case RENDERPATH_GLES2:
4630                 break;
4631         case RENDERPATH_GL11:
4632         case RENDERPATH_GL13:
4633         case RENDERPATH_GLES1:
4634                 wanttangents = false;
4635                 break;
4636         case RENDERPATH_SOFT:
4637                 break;
4638         }
4639
4640         if (r_shownormals.integer)
4641                 wanttangents = wantnormals = true;
4642
4643         // TODO: thread this
4644         // NOTE: R_PrepareRTLights() also caches entities
4645
4646         for (i = 0;i < r_refdef.scene.numentities;i++)
4647                 if (r_refdef.viewcache.entityvisible[i])
4648                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4649 }
4650
4651 //==================================================================================
4652
4653 extern cvar_t r_overheadsprites_pushback;
4654
4655 static void R_View_UpdateEntityLighting (void)
4656 {
4657         int i;
4658         entity_render_t *ent;
4659         vec3_t tempdiffusenormal, avg;
4660         vec_t f, fa, fd, fdd;
4661         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4662
4663         for (i = 0;i < r_refdef.scene.numentities;i++)
4664         {
4665                 ent = r_refdef.scene.entities[i];
4666
4667                 // skip unseen models
4668                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4669                         continue;
4670
4671                 // skip bsp models
4672                 if (ent->model && ent->model->brush.num_leafs)
4673                 {
4674                         // TODO: use modellight for r_ambient settings on world?
4675                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4676                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4677                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4678                         continue;
4679                 }
4680
4681                 // fetch the lighting from the worldmodel data
4682                 VectorClear(ent->modellight_ambient);
4683                 VectorClear(ent->modellight_diffuse);
4684                 VectorClear(tempdiffusenormal);
4685                 if (ent->flags & RENDER_LIGHT)
4686                 {
4687                         vec3_t org;
4688                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4689
4690                         // complete lightning for lit sprites
4691                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4692                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4693                         {
4694                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4695                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4696                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4697                         }
4698                         else
4699                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4700
4701                         if(ent->flags & RENDER_EQUALIZE)
4702                         {
4703                                 // first fix up ambient lighting...
4704                                 if(r_equalize_entities_minambient.value > 0)
4705                                 {
4706                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4707                                         if(fd > 0)
4708                                         {
4709                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4710                                                 if(fa < r_equalize_entities_minambient.value * fd)
4711                                                 {
4712                                                         // solve:
4713                                                         //   fa'/fd' = minambient
4714                                                         //   fa'+0.25*fd' = fa+0.25*fd
4715                                                         //   ...
4716                                                         //   fa' = fd' * minambient
4717                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4718                                                         //   ...
4719                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4720                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4721                                                         //   ...
4722                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4723                                                         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
4724                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4725                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4726                                                 }
4727                                         }
4728                                 }
4729
4730                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4731                                 {
4732                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4733                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4734                                         f = fa + 0.25 * fd;
4735                                         if(f > 0)
4736                                         {
4737                                                 // adjust brightness and saturation to target
4738                                                 avg[0] = avg[1] = avg[2] = fa / f;
4739                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4740                                                 avg[0] = avg[1] = avg[2] = fd / f;
4741                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4742                                         }
4743                                 }
4744                         }
4745                 }
4746                 else // highly rare
4747                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4748
4749                 // move the light direction into modelspace coordinates for lighting code
4750                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4751                 if(VectorLength2(ent->modellight_lightdir) == 0)
4752                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4753                 VectorNormalize(ent->modellight_lightdir);
4754         }
4755 }
4756
4757 #define MAX_LINEOFSIGHTTRACES 64
4758
4759 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4760 {
4761         int i;
4762         vec3_t boxmins, boxmaxs;
4763         vec3_t start;
4764         vec3_t end;
4765         dp_model_t *model = r_refdef.scene.worldmodel;
4766
4767         if (!model || !model->brush.TraceLineOfSight)
4768                 return true;
4769
4770         // expand the box a little
4771         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4772         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4773         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4774         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4775         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4776         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4777
4778         // return true if eye is inside enlarged box
4779         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4780                 return true;
4781
4782         // try center
4783         VectorCopy(eye, start);
4784         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4785         if (model->brush.TraceLineOfSight(model, start, end))
4786                 return true;
4787
4788         // try various random positions
4789         for (i = 0;i < numsamples;i++)
4790         {
4791                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4792                 if (model->brush.TraceLineOfSight(model, start, end))
4793                         return true;
4794         }
4795
4796         return false;
4797 }
4798
4799
4800 static void R_View_UpdateEntityVisible (void)
4801 {
4802         int i;
4803         int renderimask;
4804         int samples;
4805         entity_render_t *ent;
4806
4807         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4808                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4809                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4810                 :                                                          RENDER_EXTERIORMODEL;
4811         if (!r_drawviewmodel.integer)
4812                 renderimask |= RENDER_VIEWMODEL;
4813         if (!r_drawexteriormodel.integer)
4814                 renderimask |= RENDER_EXTERIORMODEL;
4815         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4816         {
4817                 // worldmodel can check visibility
4818                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4819                 for (i = 0;i < r_refdef.scene.numentities;i++)
4820                 {
4821                         ent = r_refdef.scene.entities[i];
4822                         if (!(ent->flags & renderimask))
4823                         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)))
4824                         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))
4825                                 r_refdef.viewcache.entityvisible[i] = true;
4826                 }
4827         }
4828         else
4829         {
4830                 // no worldmodel or it can't check visibility
4831                 for (i = 0;i < r_refdef.scene.numentities;i++)
4832                 {
4833                         ent = r_refdef.scene.entities[i];
4834                         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));
4835                 }
4836         }
4837         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4838                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4839         {
4840                 for (i = 0;i < r_refdef.scene.numentities;i++)
4841                 {
4842                         if (!r_refdef.viewcache.entityvisible[i])
4843                                 continue;
4844                         ent = r_refdef.scene.entities[i];
4845                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4846                         {
4847                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4848                                 if (samples < 0)
4849                                         continue; // temp entities do pvs only
4850                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4851                                         ent->last_trace_visibility = realtime;
4852                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4853                                         r_refdef.viewcache.entityvisible[i] = 0;
4854                         }
4855                 }
4856         }
4857 }
4858
4859 /// only used if skyrendermasked, and normally returns false
4860 int R_DrawBrushModelsSky (void)
4861 {
4862         int i, sky;
4863         entity_render_t *ent;
4864
4865         sky = false;
4866         for (i = 0;i < r_refdef.scene.numentities;i++)
4867         {
4868                 if (!r_refdef.viewcache.entityvisible[i])
4869                         continue;
4870                 ent = r_refdef.scene.entities[i];
4871                 if (!ent->model || !ent->model->DrawSky)
4872                         continue;
4873                 ent->model->DrawSky(ent);
4874                 sky = true;
4875         }
4876         return sky;
4877 }
4878
4879 static void R_DrawNoModel(entity_render_t *ent);
4880 static void R_DrawModels(void)
4881 {
4882         int i;
4883         entity_render_t *ent;
4884
4885         for (i = 0;i < r_refdef.scene.numentities;i++)
4886         {
4887                 if (!r_refdef.viewcache.entityvisible[i])
4888                         continue;
4889                 ent = r_refdef.scene.entities[i];
4890                 r_refdef.stats.entities++;
4891                 /*
4892                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4893                 {
4894                         vec3_t f, l, u, o;
4895                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4896                         Con_Printf("R_DrawModels\n");
4897                         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]);
4898                         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);
4899                         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);
4900                 }
4901                 */
4902                 if (ent->model && ent->model->Draw != NULL)
4903                         ent->model->Draw(ent);
4904                 else
4905                         R_DrawNoModel(ent);
4906         }
4907 }
4908
4909 static void R_DrawModelsDepth(void)
4910 {
4911         int i;
4912         entity_render_t *ent;
4913
4914         for (i = 0;i < r_refdef.scene.numentities;i++)
4915         {
4916                 if (!r_refdef.viewcache.entityvisible[i])
4917                         continue;
4918                 ent = r_refdef.scene.entities[i];
4919                 if (ent->model && ent->model->DrawDepth != NULL)
4920                         ent->model->DrawDepth(ent);
4921         }
4922 }
4923
4924 static void R_DrawModelsDebug(void)
4925 {
4926         int i;
4927         entity_render_t *ent;
4928
4929         for (i = 0;i < r_refdef.scene.numentities;i++)
4930         {
4931                 if (!r_refdef.viewcache.entityvisible[i])
4932                         continue;
4933                 ent = r_refdef.scene.entities[i];
4934                 if (ent->model && ent->model->DrawDebug != NULL)
4935                         ent->model->DrawDebug(ent);
4936         }
4937 }
4938
4939 static void R_DrawModelsAddWaterPlanes(void)
4940 {
4941         int i;
4942         entity_render_t *ent;
4943
4944         for (i = 0;i < r_refdef.scene.numentities;i++)
4945         {
4946                 if (!r_refdef.viewcache.entityvisible[i])
4947                         continue;
4948                 ent = r_refdef.scene.entities[i];
4949                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4950                         ent->model->DrawAddWaterPlanes(ent);
4951         }
4952 }
4953
4954 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4955 {
4956         if (r_hdr_irisadaptation.integer)
4957         {
4958                 vec3_t ambient;
4959                 vec3_t diffuse;
4960                 vec3_t diffusenormal;
4961                 vec_t brightness;
4962                 vec_t goal;
4963                 vec_t adjust;
4964                 vec_t current;
4965                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4966                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4967                 brightness = max(0.0000001f, brightness);
4968                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4969                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4970                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4971                 current = r_hdr_irisadaptation_value.value;
4972                 if (current < goal)
4973                         current = min(current + adjust, goal);
4974                 else if (current > goal)
4975                         current = max(current - adjust, goal);
4976                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4977                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4978         }
4979         else if (r_hdr_irisadaptation_value.value != 1.0f)
4980                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4981 }
4982
4983 static void R_View_SetFrustum(const int *scissor)
4984 {
4985         int i;
4986         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4987         vec3_t forward, left, up, origin, v;
4988
4989         if(scissor)
4990         {
4991                 // flipped x coordinates (because x points left here)
4992                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4993                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4994
4995                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4996                 switch(vid.renderpath)
4997                 {
4998                         case RENDERPATH_D3D9:
4999                         case RENDERPATH_D3D10:
5000                         case RENDERPATH_D3D11:
5001                                 // non-flipped y coordinates
5002                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5003                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5004                                 break;
5005                         case RENDERPATH_SOFT:
5006                         case RENDERPATH_GL11:
5007                         case RENDERPATH_GL13:
5008                         case RENDERPATH_GL20:
5009                         case RENDERPATH_GLES1:
5010                         case RENDERPATH_GLES2:
5011                                 // non-flipped y coordinates
5012                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5013                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5014                                 break;
5015                 }
5016         }
5017
5018         // we can't trust r_refdef.view.forward and friends in reflected scenes
5019         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5020
5021 #if 0
5022         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5023         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5024         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5025         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5026         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5027         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5028         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5029         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5030         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5031         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5032         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5033         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5034 #endif
5035
5036 #if 0
5037         zNear = r_refdef.nearclip;
5038         nudge = 1.0 - 1.0 / (1<<23);
5039         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5040         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5041         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5042         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5043         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5044         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5045         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5046         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5047 #endif
5048
5049
5050
5051 #if 0
5052         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5053         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5054         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5055         r_refdef.view.frustum[0].dist = m[15] - m[12];
5056
5057         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5058         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5059         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5060         r_refdef.view.frustum[1].dist = m[15] + m[12];
5061
5062         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5063         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5064         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5065         r_refdef.view.frustum[2].dist = m[15] - m[13];
5066
5067         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5068         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5069         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5070         r_refdef.view.frustum[3].dist = m[15] + m[13];
5071
5072         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5073         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5074         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5075         r_refdef.view.frustum[4].dist = m[15] - m[14];
5076
5077         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5078         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5079         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5080         r_refdef.view.frustum[5].dist = m[15] + m[14];
5081 #endif
5082
5083         if (r_refdef.view.useperspective)
5084         {
5085                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5086                 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]);
5087                 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]);
5088                 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]);
5089                 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]);
5090
5091                 // then the normals from the corners relative to origin
5092                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5093                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5094                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5095                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5096
5097                 // in a NORMAL view, forward cross left == up
5098                 // in a REFLECTED view, forward cross left == down
5099                 // so our cross products above need to be adjusted for a left handed coordinate system
5100                 CrossProduct(forward, left, v);
5101                 if(DotProduct(v, up) < 0)
5102                 {
5103                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5104                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5105                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5106                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5107                 }
5108
5109                 // Leaving those out was a mistake, those were in the old code, and they
5110                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5111                 // I couldn't reproduce it after adding those normalizations. --blub
5112                 VectorNormalize(r_refdef.view.frustum[0].normal);
5113                 VectorNormalize(r_refdef.view.frustum[1].normal);
5114                 VectorNormalize(r_refdef.view.frustum[2].normal);
5115                 VectorNormalize(r_refdef.view.frustum[3].normal);
5116
5117                 // make the corners absolute
5118                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5119                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5120                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5121                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5122
5123                 // one more normal
5124                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5125
5126                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5127                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5128                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5129                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5130                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5131         }
5132         else
5133         {
5134                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5135                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5136                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5137                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5138                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5139                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5140                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5141                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5142                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5143                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5144         }
5145         r_refdef.view.numfrustumplanes = 5;
5146
5147         if (r_refdef.view.useclipplane)
5148         {
5149                 r_refdef.view.numfrustumplanes = 6;
5150                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5151         }
5152
5153         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5154                 PlaneClassify(r_refdef.view.frustum + i);
5155
5156         // LordHavoc: note to all quake engine coders, Quake had a special case
5157         // for 90 degrees which assumed a square view (wrong), so I removed it,
5158         // Quake2 has it disabled as well.
5159
5160         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5161         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5162         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5163         //PlaneClassify(&frustum[0]);
5164
5165         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5166         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5167         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5168         //PlaneClassify(&frustum[1]);
5169
5170         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5171         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5172         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5173         //PlaneClassify(&frustum[2]);
5174
5175         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5176         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5177         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5178         //PlaneClassify(&frustum[3]);
5179
5180         // nearclip plane
5181         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5182         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5183         //PlaneClassify(&frustum[4]);
5184 }
5185
5186 void R_View_UpdateWithScissor(const int *myscissor)
5187 {
5188         R_Main_ResizeViewCache();
5189         R_View_SetFrustum(myscissor);
5190         R_View_WorldVisibility(r_refdef.view.useclipplane);
5191         R_View_UpdateEntityVisible();
5192         R_View_UpdateEntityLighting();
5193 }
5194
5195 void R_View_Update(void)
5196 {
5197         R_Main_ResizeViewCache();
5198         R_View_SetFrustum(NULL);
5199         R_View_WorldVisibility(r_refdef.view.useclipplane);
5200         R_View_UpdateEntityVisible();
5201         R_View_UpdateEntityLighting();
5202 }
5203
5204 float viewscalefpsadjusted = 1.0f;
5205
5206 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5207 {
5208         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5209         scale = bound(0.03125f, scale, 1.0f);
5210         *outwidth = (int)ceil(width * scale);
5211         *outheight = (int)ceil(height * scale);
5212 }
5213
5214 void R_Mesh_SetMainRenderTargets(void)
5215 {
5216         if (r_bloomstate.fbo_framebuffer)
5217                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5218         else
5219                 R_Mesh_ResetRenderTargets();
5220 }
5221
5222 void R_SetupView(qboolean allowwaterclippingplane)
5223 {
5224         const float *customclipplane = NULL;
5225         float plane[4];
5226         int scaledwidth, scaledheight;
5227         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5228         {
5229                 // LordHavoc: couldn't figure out how to make this approach the
5230                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5231                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5232                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5233                         dist = r_refdef.view.clipplane.dist;
5234                 plane[0] = r_refdef.view.clipplane.normal[0];
5235                 plane[1] = r_refdef.view.clipplane.normal[1];
5236                 plane[2] = r_refdef.view.clipplane.normal[2];
5237                 plane[3] = -dist;
5238                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5239         }
5240
5241         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5242         if (!r_refdef.view.useperspective)
5243                 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);
5244         else if (vid.stencil && r_useinfinitefarclip.integer)
5245                 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);
5246         else
5247                 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);
5248         R_Mesh_SetMainRenderTargets();
5249         R_SetViewport(&r_refdef.view.viewport);
5250         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5251         {
5252                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5253                 float screenplane[4];
5254                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5255                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5256                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5257                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5258                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5259         }
5260 }
5261
5262 void R_EntityMatrix(const matrix4x4_t *matrix)
5263 {
5264         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5265         {
5266                 gl_modelmatrixchanged = false;
5267                 gl_modelmatrix = *matrix;
5268                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5269                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5270                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5271                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5272                 CHECKGLERROR
5273                 switch(vid.renderpath)
5274                 {
5275                 case RENDERPATH_D3D9:
5276 #ifdef SUPPORTD3D
5277                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5278                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5279 #endif
5280                         break;
5281                 case RENDERPATH_D3D10:
5282                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5283                         break;
5284                 case RENDERPATH_D3D11:
5285                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5286                         break;
5287                 case RENDERPATH_GL11:
5288                 case RENDERPATH_GL13:
5289                 case RENDERPATH_GLES1:
5290                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5291                         break;
5292                 case RENDERPATH_SOFT:
5293                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5294                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5295                         break;
5296                 case RENDERPATH_GL20:
5297                 case RENDERPATH_GLES2:
5298                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5299                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5300                         break;
5301                 }
5302         }
5303 }
5304
5305 void R_ResetViewRendering2D(void)
5306 {
5307         r_viewport_t viewport;
5308         DrawQ_Finish();
5309
5310         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5311         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);
5312         R_Mesh_ResetRenderTargets();
5313         R_SetViewport(&viewport);
5314         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5315         GL_Color(1, 1, 1, 1);
5316         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5317         GL_BlendFunc(GL_ONE, GL_ZERO);
5318         GL_ScissorTest(false);
5319         GL_DepthMask(false);
5320         GL_DepthRange(0, 1);
5321         GL_DepthTest(false);
5322         GL_DepthFunc(GL_LEQUAL);
5323         R_EntityMatrix(&identitymatrix);
5324         R_Mesh_ResetTextureState();
5325         GL_PolygonOffset(0, 0);
5326         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5327         switch(vid.renderpath)
5328         {
5329         case RENDERPATH_GL11:
5330         case RENDERPATH_GL13:
5331         case RENDERPATH_GL20:
5332         case RENDERPATH_GLES1:
5333         case RENDERPATH_GLES2:
5334                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5335                 break;
5336         case RENDERPATH_D3D9:
5337         case RENDERPATH_D3D10:
5338         case RENDERPATH_D3D11:
5339         case RENDERPATH_SOFT:
5340                 break;
5341         }
5342         GL_CullFace(GL_NONE);
5343 }
5344
5345 void R_ResetViewRendering3D(void)
5346 {
5347         DrawQ_Finish();
5348
5349         R_SetupView(true);
5350         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5351         GL_Color(1, 1, 1, 1);
5352         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5353         GL_BlendFunc(GL_ONE, GL_ZERO);
5354         GL_ScissorTest(true);
5355         GL_DepthMask(true);
5356         GL_DepthRange(0, 1);
5357         GL_DepthTest(true);
5358         GL_DepthFunc(GL_LEQUAL);
5359         R_EntityMatrix(&identitymatrix);
5360         R_Mesh_ResetTextureState();
5361         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5362         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5363         switch(vid.renderpath)
5364         {
5365         case RENDERPATH_GL11:
5366         case RENDERPATH_GL13:
5367         case RENDERPATH_GL20:
5368         case RENDERPATH_GLES1:
5369         case RENDERPATH_GLES2:
5370                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5371                 break;
5372         case RENDERPATH_D3D9:
5373         case RENDERPATH_D3D10:
5374         case RENDERPATH_D3D11:
5375         case RENDERPATH_SOFT:
5376                 break;
5377         }
5378         GL_CullFace(r_refdef.view.cullface_back);
5379 }
5380
5381 /*
5382 ================
5383 R_RenderView_UpdateViewVectors
5384 ================
5385 */
5386 static void R_RenderView_UpdateViewVectors(void)
5387 {
5388         // break apart the view matrix into vectors for various purposes
5389         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5390         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5391         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5392         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5393         // make an inverted copy of the view matrix for tracking sprites
5394         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5395 }
5396
5397 void R_RenderScene(void);
5398 void R_RenderWaterPlanes(void);
5399
5400 static void R_Water_StartFrame(void)
5401 {
5402         int i;
5403         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5404         r_waterstate_waterplane_t *p;
5405
5406         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5407                 return;
5408
5409         switch(vid.renderpath)
5410         {
5411         case RENDERPATH_GL20:
5412         case RENDERPATH_D3D9:
5413         case RENDERPATH_D3D10:
5414         case RENDERPATH_D3D11:
5415         case RENDERPATH_SOFT:
5416         case RENDERPATH_GLES2:
5417                 break;
5418         case RENDERPATH_GL11:
5419         case RENDERPATH_GL13:
5420         case RENDERPATH_GLES1:
5421                 return;
5422         }
5423
5424         // set waterwidth and waterheight to the water resolution that will be
5425         // used (often less than the screen resolution for faster rendering)
5426         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5427
5428         // calculate desired texture sizes
5429         // can't use water if the card does not support the texture size
5430         if (!r_water.integer || r_showsurfaces.integer)
5431                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5432         else if (vid.support.arb_texture_non_power_of_two)
5433         {
5434                 texturewidth = waterwidth;
5435                 textureheight = waterheight;
5436                 camerawidth = waterwidth;
5437                 cameraheight = waterheight;
5438         }
5439         else
5440         {
5441                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5442                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5443                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5444                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5445         }
5446
5447         // allocate textures as needed
5448         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5449         {
5450                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5451                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5452                 {
5453                         if (p->texture_refraction)
5454                                 R_FreeTexture(p->texture_refraction);
5455                         p->texture_refraction = NULL;
5456                         if (p->texture_reflection)
5457                                 R_FreeTexture(p->texture_reflection);
5458                         p->texture_reflection = NULL;
5459                         if (p->texture_camera)
5460                                 R_FreeTexture(p->texture_camera);
5461                         p->texture_camera = NULL;
5462                 }
5463                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5464                 r_waterstate.texturewidth = texturewidth;
5465                 r_waterstate.textureheight = textureheight;
5466                 r_waterstate.camerawidth = camerawidth;
5467                 r_waterstate.cameraheight = cameraheight;
5468         }
5469
5470         if (r_waterstate.texturewidth)
5471         {
5472                 int scaledwidth, scaledheight;
5473
5474                 r_waterstate.enabled = true;
5475
5476                 // when doing a reduced render (HDR) we want to use a smaller area
5477                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5478                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5479                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5480
5481                 // set up variables that will be used in shader setup
5482                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5483                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5484                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5485                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5486         }
5487
5488         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5489         r_waterstate.numwaterplanes = 0;
5490 }
5491
5492 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5493 {
5494         int triangleindex, planeindex;
5495         const int *e;
5496         vec3_t vert[3];
5497         vec3_t normal;
5498         vec3_t center;
5499         mplane_t plane;
5500         r_waterstate_waterplane_t *p;
5501         texture_t *t = R_GetCurrentTexture(surface->texture);
5502
5503         // just use the first triangle with a valid normal for any decisions
5504         VectorClear(normal);
5505         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5506         {
5507                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5508                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5509                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5510                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5511                 if (VectorLength2(normal) >= 0.001)
5512                         break;
5513         }
5514
5515         VectorCopy(normal, plane.normal);
5516         VectorNormalize(plane.normal);
5517         plane.dist = DotProduct(vert[0], plane.normal);
5518         PlaneClassify(&plane);
5519         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5520         {
5521                 // skip backfaces (except if nocullface is set)
5522                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5523                         return;
5524                 VectorNegate(plane.normal, plane.normal);
5525                 plane.dist *= -1;
5526                 PlaneClassify(&plane);
5527         }
5528
5529
5530         // find a matching plane if there is one
5531         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5532                 if(p->camera_entity == t->camera_entity)
5533                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5534                                 break;
5535         if (planeindex >= r_waterstate.maxwaterplanes)
5536                 return; // nothing we can do, out of planes
5537
5538         // if this triangle does not fit any known plane rendered this frame, add one
5539         if (planeindex >= r_waterstate.numwaterplanes)
5540         {
5541                 // store the new plane
5542                 r_waterstate.numwaterplanes++;
5543                 p->plane = plane;
5544                 // clear materialflags and pvs
5545                 p->materialflags = 0;
5546                 p->pvsvalid = false;
5547                 p->camera_entity = t->camera_entity;
5548                 VectorCopy(surface->mins, p->mins);
5549                 VectorCopy(surface->maxs, p->maxs);
5550         }
5551         else
5552         {
5553                 // merge mins/maxs
5554                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5555                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5556                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5557                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5558                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5559                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5560         }
5561         // merge this surface's materialflags into the waterplane
5562         p->materialflags |= t->currentmaterialflags;
5563         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5564         {
5565                 // merge this surface's PVS into the waterplane
5566                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5567                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5568                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5569                 {
5570                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5571                         p->pvsvalid = true;
5572                 }
5573         }
5574 }
5575
5576 extern cvar_t r_drawparticles;
5577 extern cvar_t r_drawdecals;
5578
5579 static void R_Water_ProcessPlanes(void)
5580 {
5581         int myscissor[4];
5582         r_refdef_view_t originalview;
5583         r_refdef_view_t myview;
5584         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;
5585         r_waterstate_waterplane_t *p;
5586         vec3_t visorigin;
5587
5588         originalview = r_refdef.view;
5589
5590         // lowquality hack, temporarily shut down some cvars and restore afterwards
5591         qualityreduction = r_water_lowquality.integer;
5592         if (qualityreduction > 0)
5593         {
5594                 if (qualityreduction >= 1)
5595                 {
5596                         old_r_shadows = r_shadows.integer;
5597                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5598                         old_r_dlight = r_shadow_realtime_dlight.integer;
5599                         Cvar_SetValueQuick(&r_shadows, 0);
5600                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5601                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5602                 }
5603                 if (qualityreduction >= 2)
5604                 {
5605                         old_r_dynamic = r_dynamic.integer;
5606                         old_r_particles = r_drawparticles.integer;
5607                         old_r_decals = r_drawdecals.integer;
5608                         Cvar_SetValueQuick(&r_dynamic, 0);
5609                         Cvar_SetValueQuick(&r_drawparticles, 0);
5610                         Cvar_SetValueQuick(&r_drawdecals, 0);
5611                 }
5612         }
5613
5614         // make sure enough textures are allocated
5615         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5616         {
5617                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5618                 {
5619                         if (!p->texture_refraction)
5620                                 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);
5621                         if (!p->texture_refraction)
5622                                 goto error;
5623                 }
5624                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5625                 {
5626                         if (!p->texture_camera)
5627                                 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);
5628                         if (!p->texture_camera)
5629                                 goto error;
5630                 }
5631
5632                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5633                 {
5634                         if (!p->texture_reflection)
5635                                 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);
5636                         if (!p->texture_reflection)
5637                                 goto error;
5638                 }
5639         }
5640
5641         // render views
5642         r_refdef.view = originalview;
5643         r_refdef.view.showdebug = false;
5644         r_refdef.view.width = r_waterstate.waterwidth;
5645         r_refdef.view.height = r_waterstate.waterheight;
5646         r_refdef.view.useclipplane = true;
5647         myview = r_refdef.view;
5648         r_waterstate.renderingscene = true;
5649         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5650         {
5651                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5652                 {
5653                         r_refdef.view = myview;
5654                         if(r_water_scissormode.integer)
5655                         {
5656                                 R_SetupView(true);
5657                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5658                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5659                         }
5660
5661                         // render reflected scene and copy into texture
5662                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5663                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5664                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5665                         r_refdef.view.clipplane = p->plane;
5666                         // reverse the cullface settings for this render
5667                         r_refdef.view.cullface_front = GL_FRONT;
5668                         r_refdef.view.cullface_back = GL_BACK;
5669                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5670                         {
5671                                 r_refdef.view.usecustompvs = true;
5672                                 if (p->pvsvalid)
5673                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5674                                 else
5675                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5676                         }
5677
5678                         R_ResetViewRendering3D();
5679                         R_ClearScreen(r_refdef.fogenabled);
5680                         if(r_water_scissormode.integer & 2)
5681                                 R_View_UpdateWithScissor(myscissor);
5682                         else
5683                                 R_View_Update();
5684                         if(r_water_scissormode.integer & 1)
5685                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5686                         R_RenderScene();
5687
5688                         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);
5689                 }
5690
5691                 // render the normal view scene and copy into texture
5692                 // (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)
5693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5694                 {
5695                         r_refdef.view = myview;
5696                         if(r_water_scissormode.integer)
5697                         {
5698                                 R_SetupView(true);
5699                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5700                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5701                         }
5702
5703                         r_waterstate.renderingrefraction = true;
5704
5705                         r_refdef.view.clipplane = p->plane;
5706                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5707                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5708
5709                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5710                         {
5711                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5712                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5713                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5714                                 R_RenderView_UpdateViewVectors();
5715                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5716                                 {
5717                                         r_refdef.view.usecustompvs = true;
5718                                         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);
5719                                 }
5720                         }
5721
5722                         PlaneClassify(&r_refdef.view.clipplane);
5723
5724                         R_ResetViewRendering3D();
5725                         R_ClearScreen(r_refdef.fogenabled);
5726                         if(r_water_scissormode.integer & 2)
5727                                 R_View_UpdateWithScissor(myscissor);
5728                         else
5729                                 R_View_Update();
5730                         if(r_water_scissormode.integer & 1)
5731                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5732                         R_RenderScene();
5733
5734                         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);
5735                         r_waterstate.renderingrefraction = false;
5736                 }
5737                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5738                 {
5739                         r_refdef.view = myview;
5740
5741                         r_refdef.view.clipplane = p->plane;
5742                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5743                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5744
5745                         r_refdef.view.width = r_waterstate.camerawidth;
5746                         r_refdef.view.height = r_waterstate.cameraheight;
5747                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5748                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5749
5750                         if(p->camera_entity)
5751                         {
5752                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5753                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5754                         }
5755
5756                         // note: all of the view is used for displaying... so
5757                         // there is no use in scissoring
5758
5759                         // reverse the cullface settings for this render
5760                         r_refdef.view.cullface_front = GL_FRONT;
5761                         r_refdef.view.cullface_back = GL_BACK;
5762                         // also reverse the view matrix
5763                         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
5764                         R_RenderView_UpdateViewVectors();
5765                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5766                         {
5767                                 r_refdef.view.usecustompvs = true;
5768                                 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);
5769                         }
5770                         
5771                         // camera needs no clipplane
5772                         r_refdef.view.useclipplane = false;
5773
5774                         PlaneClassify(&r_refdef.view.clipplane);
5775
5776                         R_ResetViewRendering3D();
5777                         R_ClearScreen(r_refdef.fogenabled);
5778                         R_View_Update();
5779                         R_RenderScene();
5780
5781                         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);
5782                         r_waterstate.renderingrefraction = false;
5783                 }
5784
5785         }
5786         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5787         r_waterstate.renderingscene = false;
5788         r_refdef.view = originalview;
5789         R_ResetViewRendering3D();
5790         R_ClearScreen(r_refdef.fogenabled);
5791         R_View_Update();
5792         goto finish;
5793 error:
5794         r_refdef.view = originalview;
5795         r_waterstate.renderingscene = false;
5796         Cvar_SetValueQuick(&r_water, 0);
5797         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5798 finish:
5799         // lowquality hack, restore cvars
5800         if (qualityreduction > 0)
5801         {
5802                 if (qualityreduction >= 1)
5803                 {
5804                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5805                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5806                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5807                 }
5808                 if (qualityreduction >= 2)
5809                 {
5810                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5811                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5812                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5813                 }
5814         }
5815 }
5816
5817 void R_Bloom_StartFrame(void)
5818 {
5819         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5820         int viewwidth, viewheight;
5821         textype_t textype;
5822
5823         if (r_viewscale_fpsscaling.integer)
5824         {
5825                 double actualframetime;
5826                 double targetframetime;
5827                 double adjust;
5828                 actualframetime = r_refdef.lastdrawscreentime;
5829                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5830                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5831                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5832                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5833                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5834                 viewscalefpsadjusted += adjust;
5835                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5836         }
5837         else
5838                 viewscalefpsadjusted = 1.0f;
5839
5840         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5841
5842         switch(vid.renderpath)
5843         {
5844         case RENDERPATH_GL20:
5845         case RENDERPATH_D3D9:
5846         case RENDERPATH_D3D10:
5847         case RENDERPATH_D3D11:
5848         case RENDERPATH_SOFT:
5849         case RENDERPATH_GLES2:
5850                 break;
5851         case RENDERPATH_GL11:
5852         case RENDERPATH_GL13:
5853         case RENDERPATH_GLES1:
5854                 return;
5855         }
5856
5857         // set bloomwidth and bloomheight to the bloom resolution that will be
5858         // used (often less than the screen resolution for faster rendering)
5859         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5860         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5861         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5862         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5863         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5864
5865         // calculate desired texture sizes
5866         if (vid.support.arb_texture_non_power_of_two)
5867         {
5868                 screentexturewidth = vid.width;
5869                 screentextureheight = vid.height;
5870                 bloomtexturewidth = r_bloomstate.bloomwidth;
5871                 bloomtextureheight = r_bloomstate.bloomheight;
5872         }
5873         else
5874         {
5875                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5876                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5877                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5878                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5879         }
5880
5881         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))
5882         {
5883                 Cvar_SetValueQuick(&r_hdr, 0);
5884                 Cvar_SetValueQuick(&r_bloom, 0);
5885                 Cvar_SetValueQuick(&r_motionblur, 0);
5886                 Cvar_SetValueQuick(&r_damageblur, 0);
5887         }
5888
5889         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)
5890                 screentexturewidth = screentextureheight = 0;
5891         if (!r_hdr.integer && !r_bloom.integer)
5892                 bloomtexturewidth = bloomtextureheight = 0;
5893
5894         textype = TEXTYPE_COLORBUFFER;
5895         switch (vid.renderpath)
5896         {
5897         case RENDERPATH_GL20:
5898         case RENDERPATH_GLES2:
5899                 if (vid.support.ext_framebuffer_object)
5900                 {
5901                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5902                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5903                 }
5904                 break;
5905         case RENDERPATH_GL11:
5906         case RENDERPATH_GL13:
5907         case RENDERPATH_GLES1:
5908         case RENDERPATH_D3D9:
5909         case RENDERPATH_D3D10:
5910         case RENDERPATH_D3D11:
5911         case RENDERPATH_SOFT:
5912                 break;
5913         }
5914
5915         // allocate textures as needed
5916         if (r_bloomstate.screentexturewidth != screentexturewidth
5917          || r_bloomstate.screentextureheight != screentextureheight
5918          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5919          || r_bloomstate.bloomtextureheight != bloomtextureheight
5920          || r_bloomstate.texturetype != textype
5921          || r_bloomstate.viewfbo != r_viewfbo.integer)
5922         {
5923                 if (r_bloomstate.texture_bloom)
5924                         R_FreeTexture(r_bloomstate.texture_bloom);
5925                 r_bloomstate.texture_bloom = NULL;
5926                 if (r_bloomstate.texture_screen)
5927                         R_FreeTexture(r_bloomstate.texture_screen);
5928                 r_bloomstate.texture_screen = NULL;
5929                 if (r_bloomstate.fbo_framebuffer)
5930                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5931                 r_bloomstate.fbo_framebuffer = 0;
5932                 if (r_bloomstate.texture_framebuffercolor)
5933                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5934                 r_bloomstate.texture_framebuffercolor = NULL;
5935                 if (r_bloomstate.texture_framebufferdepth)
5936                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5937                 r_bloomstate.texture_framebufferdepth = NULL;
5938                 r_bloomstate.screentexturewidth = screentexturewidth;
5939                 r_bloomstate.screentextureheight = screentextureheight;
5940                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5941                         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);
5942                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5943                 {
5944                         // FIXME: choose depth bits based on a cvar
5945                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5946                         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);
5947                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5948                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5949                         // render depth into one texture and normalmap into the other
5950                         if (qglDrawBuffer)
5951                         {
5952                                 int status;
5953                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5954                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5955                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5956                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5957                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5958                         }
5959                 }
5960                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5961                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5962                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5963                         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);
5964                 r_bloomstate.viewfbo = r_viewfbo.integer;
5965                 r_bloomstate.texturetype = textype;
5966         }
5967
5968         // when doing a reduced render (HDR) we want to use a smaller area
5969         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5970         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5971         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5972         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5973         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5974
5975         // set up a texcoord array for the full resolution screen image
5976         // (we have to keep this around to copy back during final render)
5977         r_bloomstate.screentexcoord2f[0] = 0;
5978         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5979         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5980         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5981         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5982         r_bloomstate.screentexcoord2f[5] = 0;
5983         r_bloomstate.screentexcoord2f[6] = 0;
5984         r_bloomstate.screentexcoord2f[7] = 0;
5985
5986         // set up a texcoord array for the reduced resolution bloom image
5987         // (which will be additive blended over the screen image)
5988         r_bloomstate.bloomtexcoord2f[0] = 0;
5989         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5990         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5991         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5992         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5993         r_bloomstate.bloomtexcoord2f[5] = 0;
5994         r_bloomstate.bloomtexcoord2f[6] = 0;
5995         r_bloomstate.bloomtexcoord2f[7] = 0;
5996
5997         switch(vid.renderpath)
5998         {
5999         case RENDERPATH_GL11:
6000         case RENDERPATH_GL13:
6001         case RENDERPATH_GL20:
6002         case RENDERPATH_SOFT:
6003         case RENDERPATH_GLES1:
6004         case RENDERPATH_GLES2:
6005                 break;
6006         case RENDERPATH_D3D9:
6007         case RENDERPATH_D3D10:
6008         case RENDERPATH_D3D11:
6009                 {
6010                         int i;
6011                         for (i = 0;i < 4;i++)
6012                         {
6013                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6014                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6015                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6016                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6017                         }
6018                 }
6019                 break;
6020         }
6021
6022         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6023         {
6024                 r_bloomstate.enabled = true;
6025                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6026         }
6027
6028         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);
6029
6030         if (r_bloomstate.fbo_framebuffer)
6031                 r_refdef.view.clear = true;
6032 }
6033
6034 void R_Bloom_CopyBloomTexture(float colorscale)
6035 {
6036         r_refdef.stats.bloom++;
6037
6038         // scale down screen texture to the bloom texture size
6039         CHECKGLERROR
6040         R_Mesh_SetMainRenderTargets();
6041         R_SetViewport(&r_bloomstate.viewport);
6042         GL_BlendFunc(GL_ONE, GL_ZERO);
6043         GL_Color(colorscale, colorscale, colorscale, 1);
6044         // 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...
6045         switch(vid.renderpath)
6046         {
6047         case RENDERPATH_GL11:
6048         case RENDERPATH_GL13:
6049         case RENDERPATH_GL20:
6050         case RENDERPATH_GLES1:
6051         case RENDERPATH_GLES2:
6052         case RENDERPATH_SOFT:
6053                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6054                 break;
6055         case RENDERPATH_D3D9:
6056         case RENDERPATH_D3D10:
6057         case RENDERPATH_D3D11:
6058                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6059                 break;
6060         }
6061         // TODO: do boxfilter scale-down in shader?
6062         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6063         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6064         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6065
6066         // we now have a bloom image in the framebuffer
6067         // copy it into the bloom image texture for later processing
6068         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);
6069         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6070 }
6071
6072 void R_Bloom_CopyHDRTexture(void)
6073 {
6074         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);
6075         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6076 }
6077
6078 void R_Bloom_MakeTexture(void)
6079 {
6080         int x, range, dir;
6081         float xoffset, yoffset, r, brighten;
6082
6083         r_refdef.stats.bloom++;
6084
6085         R_ResetViewRendering2D();
6086
6087         // we have a bloom image in the framebuffer
6088         CHECKGLERROR
6089         R_SetViewport(&r_bloomstate.viewport);
6090
6091         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6092         {
6093                 x *= 2;
6094                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6095                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6096                 GL_Color(r,r,r,1);
6097                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6098                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6099                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6100                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6101
6102                 // copy the vertically blurred bloom view to a texture
6103                 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);
6104                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6105         }
6106
6107         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6108         brighten = r_bloom_brighten.value;
6109         if (r_bloomstate.hdr)
6110                 brighten *= r_hdr_range.value;
6111         brighten = sqrt(brighten);
6112         if(range >= 1)
6113                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6114         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6115
6116         for (dir = 0;dir < 2;dir++)
6117         {
6118                 // blend on at multiple vertical offsets to achieve a vertical blur
6119                 // TODO: do offset blends using GLSL
6120                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6121                 GL_BlendFunc(GL_ONE, GL_ZERO);
6122                 for (x = -range;x <= range;x++)
6123                 {
6124                         if (!dir){xoffset = 0;yoffset = x;}
6125                         else {xoffset = x;yoffset = 0;}
6126                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6127                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6128                         // compute a texcoord array with the specified x and y offset
6129                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6130                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6131                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6132                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6133                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6134                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6135                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6136                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6137                         // this r value looks like a 'dot' particle, fading sharply to
6138                         // black at the edges
6139                         // (probably not realistic but looks good enough)
6140                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6141                         //r = brighten/(range*2+1);
6142                         r = brighten / (range * 2 + 1);
6143                         if(range >= 1)
6144                                 r *= (1 - x*x/(float)(range*range));
6145                         GL_Color(r, r, r, 1);
6146                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6147                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6148                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6149                         GL_BlendFunc(GL_ONE, GL_ONE);
6150                 }
6151
6152                 // copy the vertically blurred bloom view to a texture
6153                 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);
6154                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6155         }
6156 }
6157
6158 void R_HDR_RenderBloomTexture(void)
6159 {
6160         int oldwidth, oldheight;
6161         float oldcolorscale;
6162         qboolean oldwaterstate;
6163
6164         oldwaterstate = r_waterstate.enabled;
6165         oldcolorscale = r_refdef.view.colorscale;
6166         oldwidth = r_refdef.view.width;
6167         oldheight = r_refdef.view.height;
6168         r_refdef.view.width = r_bloomstate.bloomwidth;
6169         r_refdef.view.height = r_bloomstate.bloomheight;
6170
6171         if(r_hdr.integer < 2)
6172                 r_waterstate.enabled = false;
6173
6174         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6175         // TODO: add exposure compensation features
6176         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6177
6178         r_refdef.view.showdebug = false;
6179         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6180
6181         R_ResetViewRendering3D();
6182
6183         R_ClearScreen(r_refdef.fogenabled);
6184         if (r_timereport_active)
6185                 R_TimeReport("HDRclear");
6186
6187         R_View_Update();
6188         if (r_timereport_active)
6189                 R_TimeReport("visibility");
6190
6191         // only do secondary renders with HDR if r_hdr is 2 or higher
6192         r_waterstate.numwaterplanes = 0;
6193         if (r_waterstate.enabled)
6194                 R_RenderWaterPlanes();
6195
6196         r_refdef.view.showdebug = true;
6197         R_RenderScene();
6198         r_waterstate.numwaterplanes = 0;
6199
6200         R_ResetViewRendering2D();
6201
6202         R_Bloom_CopyHDRTexture();
6203         R_Bloom_MakeTexture();
6204
6205         // restore the view settings
6206         r_waterstate.enabled = oldwaterstate;
6207         r_refdef.view.width = oldwidth;
6208         r_refdef.view.height = oldheight;
6209         r_refdef.view.colorscale = oldcolorscale;
6210
6211         R_ResetViewRendering3D();
6212
6213         R_ClearScreen(r_refdef.fogenabled);
6214         if (r_timereport_active)
6215                 R_TimeReport("viewclear");
6216 }
6217
6218 static void R_BlendView(void)
6219 {
6220         unsigned int permutation;
6221         float uservecs[4][4];
6222
6223         switch (vid.renderpath)
6224         {
6225         case RENDERPATH_GL20:
6226         case RENDERPATH_D3D9:
6227         case RENDERPATH_D3D10:
6228         case RENDERPATH_D3D11:
6229         case RENDERPATH_SOFT:
6230         case RENDERPATH_GLES2:
6231                 permutation =
6232                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6233                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6234                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6235                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6236                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6237
6238                 if (r_bloomstate.texture_screen)
6239                 {
6240                         // make sure the buffer is available
6241                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6242
6243                         R_ResetViewRendering2D();
6244                         R_Mesh_SetMainRenderTargets();
6245
6246                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6247                         {
6248                                 // declare variables
6249                                 float speed;
6250                                 static float avgspeed;
6251
6252                                 speed = VectorLength(cl.movement_velocity);
6253
6254                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6255                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6256
6257                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6258                                 speed = bound(0, speed, 1);
6259                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6260
6261                                 // calculate values into a standard alpha
6262                                 cl.motionbluralpha = 1 - exp(-
6263                                                 (
6264                                                  (r_motionblur.value * speed / 80)
6265                                                  +
6266                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6267                                                 )
6268                                                 /
6269                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6270                                            );
6271
6272                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6273                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6274                                 // apply the blur
6275                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6276                                 {
6277                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6278                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6279                                         switch(vid.renderpath)
6280                                         {
6281                                         case RENDERPATH_GL11:
6282                                         case RENDERPATH_GL13:
6283                                         case RENDERPATH_GL20:
6284                                         case RENDERPATH_GLES1:
6285                                         case RENDERPATH_GLES2:
6286                                         case RENDERPATH_SOFT:
6287                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6288                                                 break;
6289                                         case RENDERPATH_D3D9:
6290                                         case RENDERPATH_D3D10:
6291                                         case RENDERPATH_D3D11:
6292                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6293                                                 break;
6294                                         }
6295                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6296                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6297                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6298                                 }
6299                         }
6300
6301                         // copy view into the screen texture
6302                         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);
6303                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6304                 }
6305                 else if (!r_bloomstate.texture_bloom)
6306                 {
6307                         // we may still have to do view tint...
6308                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6309                         {
6310                                 // apply a color tint to the whole view
6311                                 R_ResetViewRendering2D();
6312                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6313                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6314                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6315                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6316                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6317                         }
6318                         break; // no screen processing, no bloom, skip it
6319                 }
6320
6321                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6322                 {
6323                         // render simple bloom effect
6324                         // copy the screen and shrink it and darken it for the bloom process
6325                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6326                         // make the bloom texture
6327                         R_Bloom_MakeTexture();
6328                 }
6329
6330 #if _MSC_VER >= 1400
6331 #define sscanf sscanf_s
6332 #endif
6333                 memset(uservecs, 0, sizeof(uservecs));
6334                 if (r_glsl_postprocess_uservec1_enable.integer)
6335                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6336                 if (r_glsl_postprocess_uservec2_enable.integer)
6337                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6338                 if (r_glsl_postprocess_uservec3_enable.integer)
6339                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6340                 if (r_glsl_postprocess_uservec4_enable.integer)
6341                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6342
6343                 R_ResetViewRendering2D();
6344                 GL_Color(1, 1, 1, 1);
6345                 GL_BlendFunc(GL_ONE, GL_ZERO);
6346
6347                 switch(vid.renderpath)
6348                 {
6349                 case RENDERPATH_GL20:
6350                 case RENDERPATH_GLES2:
6351                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6352                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6353                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6354                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6355                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6356                         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]);
6357                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6358                         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]);
6359                         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]);
6360                         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]);
6361                         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]);
6362                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6363                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6364                         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);
6365                         break;
6366                 case RENDERPATH_D3D9:
6367 #ifdef SUPPORTD3D
6368                         // 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...
6369                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6370                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6371                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6372                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6373                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6374                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6375                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6376                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6377                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6378                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6379                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6380                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6381                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6382                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6383 #endif
6384                         break;
6385                 case RENDERPATH_D3D10:
6386                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6387                         break;
6388                 case RENDERPATH_D3D11:
6389                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6390                         break;
6391                 case RENDERPATH_SOFT:
6392                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6393                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6394                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6395                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6396                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6397                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6398                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6399                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6400                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6401                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6402                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6403                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6404                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6405                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6406                         break;
6407                 default:
6408                         break;
6409                 }
6410                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6411                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6412                 break;
6413         case RENDERPATH_GL11:
6414         case RENDERPATH_GL13:
6415         case RENDERPATH_GLES1:
6416                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6417                 {
6418                         // apply a color tint to the whole view
6419                         R_ResetViewRendering2D();
6420                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6421                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6422                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6423                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6424                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6425                 }
6426                 break;
6427         }
6428 }
6429
6430 matrix4x4_t r_waterscrollmatrix;
6431
6432 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6433 {
6434         if (r_refdef.fog_density)
6435         {
6436                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6437                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6438                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6439
6440                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6441                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6442                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6443                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6444
6445                 {
6446                         vec3_t fogvec;
6447                         VectorCopy(r_refdef.fogcolor, fogvec);
6448                         //   color.rgb *= ContrastBoost * SceneBrightness;
6449                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6450                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6451                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6452                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6453                 }
6454         }
6455 }
6456
6457 void R_UpdateVariables(void)
6458 {
6459         R_Textures_Frame();
6460
6461         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6462
6463         r_refdef.farclip = r_farclip_base.value;
6464         if (r_refdef.scene.worldmodel)
6465                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6466         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6467
6468         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6469                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6470         r_refdef.polygonfactor = 0;
6471         r_refdef.polygonoffset = 0;
6472         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6473         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6474
6475         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6476         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6477         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6478         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6479         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6480         if (FAKELIGHT_ENABLED)
6481         {
6482                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6483         }
6484         if (r_showsurfaces.integer)
6485         {
6486                 r_refdef.scene.rtworld = false;
6487                 r_refdef.scene.rtworldshadows = false;
6488                 r_refdef.scene.rtdlight = false;
6489                 r_refdef.scene.rtdlightshadows = false;
6490                 r_refdef.lightmapintensity = 0;
6491         }
6492
6493         if (gamemode == GAME_NEHAHRA)
6494         {
6495                 if (gl_fogenable.integer)
6496                 {
6497                         r_refdef.oldgl_fogenable = true;
6498                         r_refdef.fog_density = gl_fogdensity.value;
6499                         r_refdef.fog_red = gl_fogred.value;
6500                         r_refdef.fog_green = gl_foggreen.value;
6501                         r_refdef.fog_blue = gl_fogblue.value;
6502                         r_refdef.fog_alpha = 1;
6503                         r_refdef.fog_start = 0;
6504                         r_refdef.fog_end = gl_skyclip.value;
6505                         r_refdef.fog_height = 1<<30;
6506                         r_refdef.fog_fadedepth = 128;
6507                 }
6508                 else if (r_refdef.oldgl_fogenable)
6509                 {
6510                         r_refdef.oldgl_fogenable = false;
6511                         r_refdef.fog_density = 0;
6512                         r_refdef.fog_red = 0;
6513                         r_refdef.fog_green = 0;
6514                         r_refdef.fog_blue = 0;
6515                         r_refdef.fog_alpha = 0;
6516                         r_refdef.fog_start = 0;
6517                         r_refdef.fog_end = 0;
6518                         r_refdef.fog_height = 1<<30;
6519                         r_refdef.fog_fadedepth = 128;
6520                 }
6521         }
6522
6523         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6524         r_refdef.fog_start = max(0, r_refdef.fog_start);
6525         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6526
6527         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6528
6529         if (r_refdef.fog_density && r_drawfog.integer)
6530         {
6531                 r_refdef.fogenabled = true;
6532                 // this is the point where the fog reaches 0.9986 alpha, which we
6533                 // consider a good enough cutoff point for the texture
6534                 // (0.9986 * 256 == 255.6)
6535                 if (r_fog_exp2.integer)
6536                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6537                 else
6538                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6539                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6540                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6541                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6542                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6543                         R_BuildFogHeightTexture();
6544                 // fog color was already set
6545                 // update the fog texture
6546                 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)
6547                         R_BuildFogTexture();
6548                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6549                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6550         }
6551         else
6552                 r_refdef.fogenabled = false;
6553
6554         switch(vid.renderpath)
6555         {
6556         case RENDERPATH_GL20:
6557         case RENDERPATH_D3D9:
6558         case RENDERPATH_D3D10:
6559         case RENDERPATH_D3D11:
6560         case RENDERPATH_SOFT:
6561         case RENDERPATH_GLES2:
6562                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6563                 {
6564                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6565                         {
6566                                 // build GLSL gamma texture
6567 #define RAMPWIDTH 256
6568                                 unsigned short ramp[RAMPWIDTH * 3];
6569                                 unsigned char rampbgr[RAMPWIDTH][4];
6570                                 int i;
6571
6572                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6573
6574                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6575                                 for(i = 0; i < RAMPWIDTH; ++i)
6576                                 {
6577                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6578                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6579                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6580                                         rampbgr[i][3] = 0;
6581                                 }
6582                                 if (r_texture_gammaramps)
6583                                 {
6584                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6585                                 }
6586                                 else
6587                                 {
6588                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6589                                 }
6590                         }
6591                 }
6592                 else
6593                 {
6594                         // remove GLSL gamma texture
6595                 }
6596                 break;
6597         case RENDERPATH_GL11:
6598         case RENDERPATH_GL13:
6599         case RENDERPATH_GLES1:
6600                 break;
6601         }
6602 }
6603
6604 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6605 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6606 /*
6607 ================
6608 R_SelectScene
6609 ================
6610 */
6611 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6612         if( scenetype != r_currentscenetype ) {
6613                 // store the old scenetype
6614                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6615                 r_currentscenetype = scenetype;
6616                 // move in the new scene
6617                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6618         }
6619 }
6620
6621 /*
6622 ================
6623 R_GetScenePointer
6624 ================
6625 */
6626 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6627 {
6628         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6629         if( scenetype == r_currentscenetype ) {
6630                 return &r_refdef.scene;
6631         } else {
6632                 return &r_scenes_store[ scenetype ];
6633         }
6634 }
6635
6636 /*
6637 ================
6638 R_RenderView
6639 ================
6640 */
6641 int dpsoftrast_test;
6642 void R_RenderView(void)
6643 {
6644         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6645
6646         dpsoftrast_test = r_test.integer;
6647
6648         if (r_timereport_active)
6649                 R_TimeReport("start");
6650         r_textureframe++; // used only by R_GetCurrentTexture
6651         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6652
6653         if(R_CompileShader_CheckStaticParms())
6654                 R_GLSL_Restart_f();
6655
6656         if (!r_drawentities.integer)
6657                 r_refdef.scene.numentities = 0;
6658
6659         R_AnimCache_ClearCache();
6660         R_FrameData_NewFrame();
6661
6662         /* adjust for stereo display */
6663         if(R_Stereo_Active())
6664         {
6665                 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);
6666                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6667         }
6668
6669         if (r_refdef.view.isoverlay)
6670         {
6671                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6672                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6673                 R_TimeReport("depthclear");
6674
6675                 r_refdef.view.showdebug = false;
6676
6677                 r_waterstate.enabled = false;
6678                 r_waterstate.numwaterplanes = 0;
6679
6680                 R_RenderScene();
6681
6682                 r_refdef.view.matrix = originalmatrix;
6683
6684                 CHECKGLERROR
6685                 return;
6686         }
6687
6688         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6689         {
6690                 r_refdef.view.matrix = originalmatrix;
6691                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6692         }
6693
6694         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6695
6696         R_RenderView_UpdateViewVectors();
6697
6698         R_Shadow_UpdateWorldLightSelection();
6699
6700         R_Bloom_StartFrame();
6701         R_Water_StartFrame();
6702
6703         CHECKGLERROR
6704         if (r_timereport_active)
6705                 R_TimeReport("viewsetup");
6706
6707         R_ResetViewRendering3D();
6708
6709         if (r_refdef.view.clear || r_refdef.fogenabled)
6710         {
6711                 R_ClearScreen(r_refdef.fogenabled);
6712                 if (r_timereport_active)
6713                         R_TimeReport("viewclear");
6714         }
6715         r_refdef.view.clear = true;
6716
6717         // this produces a bloom texture to be used in R_BlendView() later
6718         if (r_bloomstate.hdr)
6719         {
6720                 R_HDR_RenderBloomTexture();
6721                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6722                 r_textureframe++; // used only by R_GetCurrentTexture
6723         }
6724
6725         r_refdef.view.showdebug = true;
6726
6727         R_View_Update();
6728         if (r_timereport_active)
6729                 R_TimeReport("visibility");
6730
6731         r_waterstate.numwaterplanes = 0;
6732         if (r_waterstate.enabled)
6733                 R_RenderWaterPlanes();
6734
6735         R_RenderScene();
6736         r_waterstate.numwaterplanes = 0;
6737
6738         R_BlendView();
6739         if (r_timereport_active)
6740                 R_TimeReport("blendview");
6741
6742         GL_Scissor(0, 0, vid.width, vid.height);
6743         GL_ScissorTest(false);
6744
6745         r_refdef.view.matrix = originalmatrix;
6746
6747         CHECKGLERROR
6748 }
6749
6750 void R_RenderWaterPlanes(void)
6751 {
6752         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6753         {
6754                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6755                 if (r_timereport_active)
6756                         R_TimeReport("waterworld");
6757         }
6758
6759         // don't let sound skip if going slow
6760         if (r_refdef.scene.extraupdate)
6761                 S_ExtraUpdate ();
6762
6763         R_DrawModelsAddWaterPlanes();
6764         if (r_timereport_active)
6765                 R_TimeReport("watermodels");
6766
6767         if (r_waterstate.numwaterplanes)
6768         {
6769                 R_Water_ProcessPlanes();
6770                 if (r_timereport_active)
6771                         R_TimeReport("waterscenes");
6772         }
6773 }
6774
6775 extern void R_DrawLightningBeams (void);
6776 extern void VM_CL_AddPolygonsToMeshQueue (void);
6777 extern void R_DrawPortals (void);
6778 extern cvar_t cl_locs_show;
6779 static void R_DrawLocs(void);
6780 static void R_DrawEntityBBoxes(void);
6781 static void R_DrawModelDecals(void);
6782 extern void R_DrawModelShadows(void);
6783 extern void R_DrawModelShadowMaps(void);
6784 extern cvar_t cl_decals_newsystem;
6785 extern qboolean r_shadow_usingdeferredprepass;
6786 void R_RenderScene(void)
6787 {
6788         qboolean shadowmapping = false;
6789
6790         if (r_timereport_active)
6791                 R_TimeReport("beginscene");
6792
6793         r_refdef.stats.renders++;
6794
6795         R_UpdateFogColor();
6796
6797         // don't let sound skip if going slow
6798         if (r_refdef.scene.extraupdate)
6799                 S_ExtraUpdate ();
6800
6801         R_MeshQueue_BeginScene();
6802
6803         R_SkyStartFrame();
6804
6805         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);
6806
6807         if (r_timereport_active)
6808                 R_TimeReport("skystartframe");
6809
6810         if (cl.csqc_vidvars.drawworld)
6811         {
6812                 // don't let sound skip if going slow
6813                 if (r_refdef.scene.extraupdate)
6814                         S_ExtraUpdate ();
6815
6816                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6817                 {
6818                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6819                         if (r_timereport_active)
6820                                 R_TimeReport("worldsky");
6821                 }
6822
6823                 if (R_DrawBrushModelsSky() && r_timereport_active)
6824                         R_TimeReport("bmodelsky");
6825
6826                 if (skyrendermasked && skyrenderlater)
6827                 {
6828                         // we have to force off the water clipping plane while rendering sky
6829                         R_SetupView(false);
6830                         R_Sky();
6831                         R_SetupView(true);
6832                         if (r_timereport_active)
6833                                 R_TimeReport("sky");
6834                 }
6835         }
6836
6837         R_AnimCache_CacheVisibleEntities();
6838         if (r_timereport_active)
6839                 R_TimeReport("animation");
6840
6841         R_Shadow_PrepareLights();
6842         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6843                 R_Shadow_PrepareModelShadows();
6844         if (r_timereport_active)
6845                 R_TimeReport("preparelights");
6846
6847         if (R_Shadow_ShadowMappingEnabled())
6848                 shadowmapping = true;
6849
6850         if (r_shadow_usingdeferredprepass)
6851                 R_Shadow_DrawPrepass();
6852
6853         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6854         {
6855                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6856                 if (r_timereport_active)
6857                         R_TimeReport("worlddepth");
6858         }
6859         if (r_depthfirst.integer >= 2)
6860         {
6861                 R_DrawModelsDepth();
6862                 if (r_timereport_active)
6863                         R_TimeReport("modeldepth");
6864         }
6865
6866         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6867         {
6868                 R_DrawModelShadowMaps();
6869                 R_ResetViewRendering3D();
6870                 // don't let sound skip if going slow
6871                 if (r_refdef.scene.extraupdate)
6872                         S_ExtraUpdate ();
6873         }
6874
6875         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6876         {
6877                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6878                 if (r_timereport_active)
6879                         R_TimeReport("world");
6880         }
6881
6882         // don't let sound skip if going slow
6883         if (r_refdef.scene.extraupdate)
6884                 S_ExtraUpdate ();
6885
6886         R_DrawModels();
6887         if (r_timereport_active)
6888                 R_TimeReport("models");
6889
6890         // don't let sound skip if going slow
6891         if (r_refdef.scene.extraupdate)
6892                 S_ExtraUpdate ();
6893
6894         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6895         {
6896                 R_DrawModelShadows();
6897                 R_ResetViewRendering3D();
6898                 // don't let sound skip if going slow
6899                 if (r_refdef.scene.extraupdate)
6900                         S_ExtraUpdate ();
6901         }
6902
6903         if (!r_shadow_usingdeferredprepass)
6904         {
6905                 R_Shadow_DrawLights();
6906                 if (r_timereport_active)
6907                         R_TimeReport("rtlights");
6908         }
6909
6910         // don't let sound skip if going slow
6911         if (r_refdef.scene.extraupdate)
6912                 S_ExtraUpdate ();
6913
6914         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6915         {
6916                 R_DrawModelShadows();
6917                 R_ResetViewRendering3D();
6918                 // don't let sound skip if going slow
6919                 if (r_refdef.scene.extraupdate)
6920                         S_ExtraUpdate ();
6921         }
6922
6923         if (cl.csqc_vidvars.drawworld)
6924         {
6925                 if (cl_decals_newsystem.integer)
6926                 {
6927                         R_DrawModelDecals();
6928                         if (r_timereport_active)
6929                                 R_TimeReport("modeldecals");
6930                 }
6931                 else
6932                 {
6933                         R_DrawDecals();
6934                         if (r_timereport_active)
6935                                 R_TimeReport("decals");
6936                 }
6937
6938                 R_DrawParticles();
6939                 if (r_timereport_active)
6940                         R_TimeReport("particles");
6941
6942                 R_DrawExplosions();
6943                 if (r_timereport_active)
6944                         R_TimeReport("explosions");
6945
6946                 R_DrawLightningBeams();
6947                 if (r_timereport_active)
6948                         R_TimeReport("lightning");
6949         }
6950
6951         VM_CL_AddPolygonsToMeshQueue();
6952
6953         if (r_refdef.view.showdebug)
6954         {
6955                 if (cl_locs_show.integer)
6956                 {
6957                         R_DrawLocs();
6958                         if (r_timereport_active)
6959                                 R_TimeReport("showlocs");
6960                 }
6961
6962                 if (r_drawportals.integer)
6963                 {
6964                         R_DrawPortals();
6965                         if (r_timereport_active)
6966                                 R_TimeReport("portals");
6967                 }
6968
6969                 if (r_showbboxes.value > 0)
6970                 {
6971                         R_DrawEntityBBoxes();
6972                         if (r_timereport_active)
6973                                 R_TimeReport("bboxes");
6974                 }
6975         }
6976
6977         if (r_transparent.integer)
6978         {
6979                 R_MeshQueue_RenderTransparent();
6980                 if (r_timereport_active)
6981                         R_TimeReport("drawtrans");
6982         }
6983
6984         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))
6985         {
6986                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6987                 if (r_timereport_active)
6988                         R_TimeReport("worlddebug");
6989                 R_DrawModelsDebug();
6990                 if (r_timereport_active)
6991                         R_TimeReport("modeldebug");
6992         }
6993
6994         if (cl.csqc_vidvars.drawworld)
6995         {
6996                 R_Shadow_DrawCoronas();
6997                 if (r_timereport_active)
6998                         R_TimeReport("coronas");
6999         }
7000
7001 #if 0
7002         {
7003                 GL_DepthTest(false);
7004                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7005                 GL_Color(1, 1, 1, 1);
7006                 qglBegin(GL_POLYGON);
7007                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7008                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7009                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7010                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7011                 qglEnd();
7012                 qglBegin(GL_POLYGON);
7013                 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]);
7014                 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]);
7015                 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]);
7016                 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]);
7017                 qglEnd();
7018                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7019         }
7020 #endif
7021
7022         // don't let sound skip if going slow
7023         if (r_refdef.scene.extraupdate)
7024                 S_ExtraUpdate ();
7025
7026         R_ResetViewRendering2D();
7027 }
7028
7029 static const unsigned short bboxelements[36] =
7030 {
7031         5, 1, 3, 5, 3, 7,
7032         6, 2, 0, 6, 0, 4,
7033         7, 3, 2, 7, 2, 6,
7034         4, 0, 1, 4, 1, 5,
7035         4, 5, 7, 4, 7, 6,
7036         1, 0, 2, 1, 2, 3,
7037 };
7038
7039 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7040 {
7041         int i;
7042         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7043
7044         RSurf_ActiveWorldEntity();
7045
7046         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7047         GL_DepthMask(false);
7048         GL_DepthRange(0, 1);
7049         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7050 //      R_Mesh_ResetTextureState();
7051
7052         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7053         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7054         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7055         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7056         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7057         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7058         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7059         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7060         R_FillColors(color4f, 8, cr, cg, cb, ca);
7061         if (r_refdef.fogenabled)
7062         {
7063                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7064                 {
7065                         f1 = RSurf_FogVertex(v);
7066                         f2 = 1 - f1;
7067                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7068                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7069                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7070                 }
7071         }
7072         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7073         R_Mesh_ResetTextureState();
7074         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7075         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7076 }
7077
7078 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7079 {
7080         int i;
7081         float color[4];
7082         prvm_edict_t *edict;
7083         prvm_prog_t *prog_save = prog;
7084
7085         // this function draws bounding boxes of server entities
7086         if (!sv.active)
7087                 return;
7088
7089         GL_CullFace(GL_NONE);
7090         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7091
7092         prog = 0;
7093         SV_VM_Begin();
7094         for (i = 0;i < numsurfaces;i++)
7095         {
7096                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7097                 switch ((int)edict->fields.server->solid)
7098                 {
7099                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7100                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7101                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7102                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7103                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7104                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7105                 }
7106                 color[3] *= r_showbboxes.value;
7107                 color[3] = bound(0, color[3], 1);
7108                 GL_DepthTest(!r_showdisabledepthtest.integer);
7109                 GL_CullFace(r_refdef.view.cullface_front);
7110                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7111         }
7112         SV_VM_End();
7113         prog = prog_save;
7114 }
7115
7116 static void R_DrawEntityBBoxes(void)
7117 {
7118         int i;
7119         prvm_edict_t *edict;
7120         vec3_t center;
7121         prvm_prog_t *prog_save = prog;
7122
7123         // this function draws bounding boxes of server entities
7124         if (!sv.active)
7125                 return;
7126
7127         prog = 0;
7128         SV_VM_Begin();
7129         for (i = 0;i < prog->num_edicts;i++)
7130         {
7131                 edict = PRVM_EDICT_NUM(i);
7132                 if (edict->priv.server->free)
7133                         continue;
7134                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7135                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7136                         continue;
7137                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7138                         continue;
7139                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7140                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7141         }
7142         SV_VM_End();
7143         prog = prog_save;
7144 }
7145
7146 static const int nomodelelement3i[24] =
7147 {
7148         5, 2, 0,
7149         5, 1, 2,
7150         5, 0, 3,
7151         5, 3, 1,
7152         0, 2, 4,
7153         2, 1, 4,
7154         3, 0, 4,
7155         1, 3, 4
7156 };
7157
7158 static const unsigned short nomodelelement3s[24] =
7159 {
7160         5, 2, 0,
7161         5, 1, 2,
7162         5, 0, 3,
7163         5, 3, 1,
7164         0, 2, 4,
7165         2, 1, 4,
7166         3, 0, 4,
7167         1, 3, 4
7168 };
7169
7170 static const float nomodelvertex3f[6*3] =
7171 {
7172         -16,   0,   0,
7173          16,   0,   0,
7174           0, -16,   0,
7175           0,  16,   0,
7176           0,   0, -16,
7177           0,   0,  16
7178 };
7179
7180 static const float nomodelcolor4f[6*4] =
7181 {
7182         0.0f, 0.0f, 0.5f, 1.0f,
7183         0.0f, 0.0f, 0.5f, 1.0f,
7184         0.0f, 0.5f, 0.0f, 1.0f,
7185         0.0f, 0.5f, 0.0f, 1.0f,
7186         0.5f, 0.0f, 0.0f, 1.0f,
7187         0.5f, 0.0f, 0.0f, 1.0f
7188 };
7189
7190 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7191 {
7192         int i;
7193         float f1, f2, *c;
7194         float color4f[6*4];
7195
7196         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);
7197
7198         // this is only called once per entity so numsurfaces is always 1, and
7199         // surfacelist is always {0}, so this code does not handle batches
7200
7201         if (rsurface.ent_flags & RENDER_ADDITIVE)
7202         {
7203                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7204                 GL_DepthMask(false);
7205         }
7206         else if (rsurface.colormod[3] < 1)
7207         {
7208                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7209                 GL_DepthMask(false);
7210         }
7211         else
7212         {
7213                 GL_BlendFunc(GL_ONE, GL_ZERO);
7214                 GL_DepthMask(true);
7215         }
7216         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7217         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7218         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7219         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7220         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7221         for (i = 0, c = color4f;i < 6;i++, c += 4)
7222         {
7223                 c[0] *= rsurface.colormod[0];
7224                 c[1] *= rsurface.colormod[1];
7225                 c[2] *= rsurface.colormod[2];
7226                 c[3] *= rsurface.colormod[3];
7227         }
7228         if (r_refdef.fogenabled)
7229         {
7230                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7231                 {
7232                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7233                         f2 = 1 - f1;
7234                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7235                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7236                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7237                 }
7238         }
7239 //      R_Mesh_ResetTextureState();
7240         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7241         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7242         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7243 }
7244
7245 void R_DrawNoModel(entity_render_t *ent)
7246 {
7247         vec3_t org;
7248         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7249         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7250                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7251         else
7252                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7253 }
7254
7255 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7256 {
7257         vec3_t right1, right2, diff, normal;
7258
7259         VectorSubtract (org2, org1, normal);
7260
7261         // calculate 'right' vector for start
7262         VectorSubtract (r_refdef.view.origin, org1, diff);
7263         CrossProduct (normal, diff, right1);
7264         VectorNormalize (right1);
7265
7266         // calculate 'right' vector for end
7267         VectorSubtract (r_refdef.view.origin, org2, diff);
7268         CrossProduct (normal, diff, right2);
7269         VectorNormalize (right2);
7270
7271         vert[ 0] = org1[0] + width * right1[0];
7272         vert[ 1] = org1[1] + width * right1[1];
7273         vert[ 2] = org1[2] + width * right1[2];
7274         vert[ 3] = org1[0] - width * right1[0];
7275         vert[ 4] = org1[1] - width * right1[1];
7276         vert[ 5] = org1[2] - width * right1[2];
7277         vert[ 6] = org2[0] - width * right2[0];
7278         vert[ 7] = org2[1] - width * right2[1];
7279         vert[ 8] = org2[2] - width * right2[2];
7280         vert[ 9] = org2[0] + width * right2[0];
7281         vert[10] = org2[1] + width * right2[1];
7282         vert[11] = org2[2] + width * right2[2];
7283 }
7284
7285 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)
7286 {
7287         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7288         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7289         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7290         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7291         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7292         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7293         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7294         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7295         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7296         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7297         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7298         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7299 }
7300
7301 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7302 {
7303         int i;
7304         float *vertex3f;
7305         float v[3];
7306         VectorSet(v, x, y, z);
7307         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7308                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7309                         break;
7310         if (i == mesh->numvertices)
7311         {
7312                 if (mesh->numvertices < mesh->maxvertices)
7313                 {
7314                         VectorCopy(v, vertex3f);
7315                         mesh->numvertices++;
7316                 }
7317                 return mesh->numvertices;
7318         }
7319         else
7320                 return i;
7321 }
7322
7323 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7324 {
7325         int i;
7326         int *e, element[3];
7327         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7328         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7329         e = mesh->element3i + mesh->numtriangles * 3;
7330         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7331         {
7332                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7333                 if (mesh->numtriangles < mesh->maxtriangles)
7334                 {
7335                         *e++ = element[0];
7336                         *e++ = element[1];
7337                         *e++ = element[2];
7338                         mesh->numtriangles++;
7339                 }
7340                 element[1] = element[2];
7341         }
7342 }
7343
7344 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7345 {
7346         int i;
7347         int *e, element[3];
7348         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7349         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7350         e = mesh->element3i + mesh->numtriangles * 3;
7351         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7352         {
7353                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7354                 if (mesh->numtriangles < mesh->maxtriangles)
7355                 {
7356                         *e++ = element[0];
7357                         *e++ = element[1];
7358                         *e++ = element[2];
7359                         mesh->numtriangles++;
7360                 }
7361                 element[1] = element[2];
7362         }
7363 }
7364
7365 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7366 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7367 {
7368         int planenum, planenum2;
7369         int w;
7370         int tempnumpoints;
7371         mplane_t *plane, *plane2;
7372         double maxdist;
7373         double temppoints[2][256*3];
7374         // figure out how large a bounding box we need to properly compute this brush
7375         maxdist = 0;
7376         for (w = 0;w < numplanes;w++)
7377                 maxdist = max(maxdist, fabs(planes[w].dist));
7378         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7379         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7380         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7381         {
7382                 w = 0;
7383                 tempnumpoints = 4;
7384                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7385                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7386                 {
7387                         if (planenum2 == planenum)
7388                                 continue;
7389                         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);
7390                         w = !w;
7391                 }
7392                 if (tempnumpoints < 3)
7393                         continue;
7394                 // generate elements forming a triangle fan for this polygon
7395                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7396         }
7397 }
7398
7399 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)
7400 {
7401         texturelayer_t *layer;
7402         layer = t->currentlayers + t->currentnumlayers++;
7403         layer->type = type;
7404         layer->depthmask = depthmask;
7405         layer->blendfunc1 = blendfunc1;
7406         layer->blendfunc2 = blendfunc2;
7407         layer->texture = texture;
7408         layer->texmatrix = *matrix;
7409         layer->color[0] = r;
7410         layer->color[1] = g;
7411         layer->color[2] = b;
7412         layer->color[3] = a;
7413 }
7414
7415 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7416 {
7417         if(parms[0] == 0 && parms[1] == 0)
7418                 return false;
7419         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7420                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7421                         return false;
7422         return true;
7423 }
7424
7425 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7426 {
7427         double index, f;
7428         index = parms[2] + rsurface.shadertime * parms[3];
7429         index -= floor(index);
7430         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7431         {
7432         default:
7433         case Q3WAVEFUNC_NONE:
7434         case Q3WAVEFUNC_NOISE:
7435         case Q3WAVEFUNC_COUNT:
7436                 f = 0;
7437                 break;
7438         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7439         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7440         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7441         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7442         case Q3WAVEFUNC_TRIANGLE:
7443                 index *= 4;
7444                 f = index - floor(index);
7445                 if (index < 1)
7446                         f = f;
7447                 else if (index < 2)
7448                         f = 1 - f;
7449                 else if (index < 3)
7450                         f = -f;
7451                 else
7452                         f = -(1 - f);
7453                 break;
7454         }
7455         f = parms[0] + parms[1] * f;
7456         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7457                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7458         return (float) f;
7459 }
7460
7461 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7462 {
7463         int w, h, idx;
7464         double f;
7465         double offsetd[2];
7466         float tcmat[12];
7467         matrix4x4_t matrix, temp;
7468         switch(tcmod->tcmod)
7469         {
7470                 case Q3TCMOD_COUNT:
7471                 case Q3TCMOD_NONE:
7472                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7473                                 matrix = r_waterscrollmatrix;
7474                         else
7475                                 matrix = identitymatrix;
7476                         break;
7477                 case Q3TCMOD_ENTITYTRANSLATE:
7478                         // this is used in Q3 to allow the gamecode to control texcoord
7479                         // scrolling on the entity, which is not supported in darkplaces yet.
7480                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7481                         break;
7482                 case Q3TCMOD_ROTATE:
7483                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7484                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7485                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7486                         break;
7487                 case Q3TCMOD_SCALE:
7488                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7489                         break;
7490                 case Q3TCMOD_SCROLL:
7491                         // extra care is needed because of precision breakdown with large values of time
7492                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7493                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7494                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7495                         break;
7496                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7497                         w = (int) tcmod->parms[0];
7498                         h = (int) tcmod->parms[1];
7499                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7500                         f = f - floor(f);
7501                         idx = (int) floor(f * w * h);
7502                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7503                         break;
7504                 case Q3TCMOD_STRETCH:
7505                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7506                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7507                         break;
7508                 case Q3TCMOD_TRANSFORM:
7509                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7510                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7511                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7512                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7513                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7514                         break;
7515                 case Q3TCMOD_TURBULENT:
7516                         // this is handled in the RSurf_PrepareVertices function
7517                         matrix = identitymatrix;
7518                         break;
7519         }
7520         temp = *texmatrix;
7521         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7522 }
7523
7524 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7525 {
7526         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7527         char name[MAX_QPATH];
7528         skinframe_t *skinframe;
7529         unsigned char pixels[296*194];
7530         strlcpy(cache->name, skinname, sizeof(cache->name));
7531         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7532         if (developer_loading.integer)
7533                 Con_Printf("loading %s\n", name);
7534         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7535         if (!skinframe || !skinframe->base)
7536         {
7537                 unsigned char *f;
7538                 fs_offset_t filesize;
7539                 skinframe = NULL;
7540                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7541                 if (f)
7542                 {
7543                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7544                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7545                         Mem_Free(f);
7546                 }
7547         }
7548         cache->skinframe = skinframe;
7549 }
7550
7551 texture_t *R_GetCurrentTexture(texture_t *t)
7552 {
7553         int i;
7554         const entity_render_t *ent = rsurface.entity;
7555         dp_model_t *model = ent->model;
7556         q3shaderinfo_layer_tcmod_t *tcmod;
7557
7558         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7559                 return t->currentframe;
7560         t->update_lastrenderframe = r_textureframe;
7561         t->update_lastrenderentity = (void *)ent;
7562
7563         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7564                 t->camera_entity = ent->entitynumber;
7565         else
7566                 t->camera_entity = 0;
7567
7568         // switch to an alternate material if this is a q1bsp animated material
7569         {
7570                 texture_t *texture = t;
7571                 int s = rsurface.ent_skinnum;
7572                 if ((unsigned int)s >= (unsigned int)model->numskins)
7573                         s = 0;
7574                 if (model->skinscenes)
7575                 {
7576                         if (model->skinscenes[s].framecount > 1)
7577                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7578                         else
7579                                 s = model->skinscenes[s].firstframe;
7580                 }
7581                 if (s > 0)
7582                         t = t + s * model->num_surfaces;
7583                 if (t->animated)
7584                 {
7585                         // use an alternate animation if the entity's frame is not 0,
7586                         // and only if the texture has an alternate animation
7587                         if (rsurface.ent_alttextures && t->anim_total[1])
7588                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7589                         else
7590                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7591                 }
7592                 texture->currentframe = t;
7593         }
7594
7595         // update currentskinframe to be a qw skin or animation frame
7596         if (rsurface.ent_qwskin >= 0)
7597         {
7598                 i = rsurface.ent_qwskin;
7599                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7600                 {
7601                         r_qwskincache_size = cl.maxclients;
7602                         if (r_qwskincache)
7603                                 Mem_Free(r_qwskincache);
7604                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7605                 }
7606                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7607                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7608                 t->currentskinframe = r_qwskincache[i].skinframe;
7609                 if (t->currentskinframe == NULL)
7610                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7611         }
7612         else if (t->numskinframes >= 2)
7613                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7614         if (t->backgroundnumskinframes >= 2)
7615                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7616
7617         t->currentmaterialflags = t->basematerialflags;
7618         t->currentalpha = rsurface.colormod[3];
7619         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7620                 t->currentalpha *= r_wateralpha.value;
7621         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7622                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7623         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7624                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7625         if (!(rsurface.ent_flags & RENDER_LIGHT))
7626                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7627         else if (FAKELIGHT_ENABLED)
7628         {
7629                 // no modellight if using fakelight for the map
7630         }
7631         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7632         {
7633                 // pick a model lighting mode
7634                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7635                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7636                 else
7637                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7638         }
7639         if (rsurface.ent_flags & RENDER_ADDITIVE)
7640                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7641         else if (t->currentalpha < 1)
7642                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7643         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7644                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7645         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7646                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7647         if (t->backgroundnumskinframes)
7648                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7649         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7650         {
7651                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7652                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7653         }
7654         else
7655                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7656         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7657                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7658
7659         // there is no tcmod
7660         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7661         {
7662                 t->currenttexmatrix = r_waterscrollmatrix;
7663                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7664         }
7665         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7666         {
7667                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7668                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7669         }
7670
7671         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7672                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7673         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7674                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7675
7676         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7677         if (t->currentskinframe->qpixels)
7678                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7679         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7680         if (!t->basetexture)
7681                 t->basetexture = r_texture_notexture;
7682         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7683         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7684         t->nmaptexture = t->currentskinframe->nmap;
7685         if (!t->nmaptexture)
7686                 t->nmaptexture = r_texture_blanknormalmap;
7687         t->glosstexture = r_texture_black;
7688         t->glowtexture = t->currentskinframe->glow;
7689         t->fogtexture = t->currentskinframe->fog;
7690         t->reflectmasktexture = t->currentskinframe->reflect;
7691         if (t->backgroundnumskinframes)
7692         {
7693                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7694                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7695                 t->backgroundglosstexture = r_texture_black;
7696                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7697                 if (!t->backgroundnmaptexture)
7698                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7699         }
7700         else
7701         {
7702                 t->backgroundbasetexture = r_texture_white;
7703                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7704                 t->backgroundglosstexture = r_texture_black;
7705                 t->backgroundglowtexture = NULL;
7706         }
7707         t->specularpower = r_shadow_glossexponent.value;
7708         // TODO: store reference values for these in the texture?
7709         t->specularscale = 0;
7710         if (r_shadow_gloss.integer > 0)
7711         {
7712                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7713                 {
7714                         if (r_shadow_glossintensity.value > 0)
7715                         {
7716                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7717                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7718                                 t->specularscale = r_shadow_glossintensity.value;
7719                         }
7720                 }
7721                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7722                 {
7723                         t->glosstexture = r_texture_white;
7724                         t->backgroundglosstexture = r_texture_white;
7725                         t->specularscale = r_shadow_gloss2intensity.value;
7726                         t->specularpower = r_shadow_gloss2exponent.value;
7727                 }
7728         }
7729         t->specularscale *= t->specularscalemod;
7730         t->specularpower *= t->specularpowermod;
7731
7732         // lightmaps mode looks bad with dlights using actual texturing, so turn
7733         // off the colormap and glossmap, but leave the normalmap on as it still
7734         // accurately represents the shading involved
7735         if (gl_lightmaps.integer)
7736         {
7737                 t->basetexture = r_texture_grey128;
7738                 t->pantstexture = r_texture_black;
7739                 t->shirttexture = r_texture_black;
7740                 t->nmaptexture = r_texture_blanknormalmap;
7741                 t->glosstexture = r_texture_black;
7742                 t->glowtexture = NULL;
7743                 t->fogtexture = NULL;
7744                 t->reflectmasktexture = NULL;
7745                 t->backgroundbasetexture = NULL;
7746                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7747                 t->backgroundglosstexture = r_texture_black;
7748                 t->backgroundglowtexture = NULL;
7749                 t->specularscale = 0;
7750                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7751         }
7752
7753         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7754         VectorClear(t->dlightcolor);
7755         t->currentnumlayers = 0;
7756         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7757         {
7758                 int blendfunc1, blendfunc2;
7759                 qboolean depthmask;
7760                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7761                 {
7762                         blendfunc1 = GL_SRC_ALPHA;
7763                         blendfunc2 = GL_ONE;
7764                 }
7765                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7766                 {
7767                         blendfunc1 = GL_SRC_ALPHA;
7768                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7769                 }
7770                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7771                 {
7772                         blendfunc1 = t->customblendfunc[0];
7773                         blendfunc2 = t->customblendfunc[1];
7774                 }
7775                 else
7776                 {
7777                         blendfunc1 = GL_ONE;
7778                         blendfunc2 = GL_ZERO;
7779                 }
7780                 // don't colormod evilblend textures
7781                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7782                         VectorSet(t->lightmapcolor, 1, 1, 1);
7783                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7784                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7785                 {
7786                         // fullbright is not affected by r_refdef.lightmapintensity
7787                         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]);
7788                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7789                                 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]);
7790                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7791                                 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]);
7792                 }
7793                 else
7794                 {
7795                         vec3_t ambientcolor;
7796                         float colorscale;
7797                         // set the color tint used for lights affecting this surface
7798                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7799                         colorscale = 2;
7800                         // q3bsp has no lightmap updates, so the lightstylevalue that
7801                         // would normally be baked into the lightmap must be
7802                         // applied to the color
7803                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7804                         if (model->type == mod_brushq3)
7805                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7806                         colorscale *= r_refdef.lightmapintensity;
7807                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7808                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7809                         // basic lit geometry
7810                         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]);
7811                         // add pants/shirt if needed
7812                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7813                                 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]);
7814                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7815                                 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]);
7816                         // now add ambient passes if needed
7817                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7818                         {
7819                                 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]);
7820                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7821                                         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]);
7822                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7823                                         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]);
7824                         }
7825                 }
7826                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7827                         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]);
7828                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7829                 {
7830                         // if this is opaque use alpha blend which will darken the earlier
7831                         // passes cheaply.
7832                         //
7833                         // if this is an alpha blended material, all the earlier passes
7834                         // were darkened by fog already, so we only need to add the fog
7835                         // color ontop through the fog mask texture
7836                         //
7837                         // if this is an additive blended material, all the earlier passes
7838                         // were darkened by fog already, and we should not add fog color
7839                         // (because the background was not darkened, there is no fog color
7840                         // that was lost behind it).
7841                         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]);
7842                 }
7843         }
7844
7845         return t->currentframe;
7846 }
7847
7848 rsurfacestate_t rsurface;
7849
7850 void RSurf_ActiveWorldEntity(void)
7851 {
7852         dp_model_t *model = r_refdef.scene.worldmodel;
7853         //if (rsurface.entity == r_refdef.scene.worldentity)
7854         //      return;
7855         rsurface.entity = r_refdef.scene.worldentity;
7856         rsurface.skeleton = NULL;
7857         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7858         rsurface.ent_skinnum = 0;
7859         rsurface.ent_qwskin = -1;
7860         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7861         rsurface.shadertime = r_refdef.scene.time;
7862         rsurface.matrix = identitymatrix;
7863         rsurface.inversematrix = identitymatrix;
7864         rsurface.matrixscale = 1;
7865         rsurface.inversematrixscale = 1;
7866         R_EntityMatrix(&identitymatrix);
7867         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7868         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7869         rsurface.fograngerecip = r_refdef.fograngerecip;
7870         rsurface.fogheightfade = r_refdef.fogheightfade;
7871         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7872         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7873         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7874         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7875         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7876         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7877         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7878         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7879         rsurface.colormod[3] = 1;
7880         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);
7881         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7882         rsurface.frameblend[0].lerp = 1;
7883         rsurface.ent_alttextures = false;
7884         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7885         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7886         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7887         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7888         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7889         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7890         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7891         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7892         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7893         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7894         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7895         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7896         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7897         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7898         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7899         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7900         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7901         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7902         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7903         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7904         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7905         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7906         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7907         rsurface.modelelement3i = model->surfmesh.data_element3i;
7908         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7909         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7910         rsurface.modelelement3s = model->surfmesh.data_element3s;
7911         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7912         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7913         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7914         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7915         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7916         rsurface.modelsurfaces = model->data_surfaces;
7917         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7918         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7919         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7920         rsurface.modelgeneratedvertex = false;
7921         rsurface.batchgeneratedvertex = false;
7922         rsurface.batchfirstvertex = 0;
7923         rsurface.batchnumvertices = 0;
7924         rsurface.batchfirsttriangle = 0;
7925         rsurface.batchnumtriangles = 0;
7926         rsurface.batchvertex3f  = NULL;
7927         rsurface.batchvertex3f_vertexbuffer = NULL;
7928         rsurface.batchvertex3f_bufferoffset = 0;
7929         rsurface.batchsvector3f = NULL;
7930         rsurface.batchsvector3f_vertexbuffer = NULL;
7931         rsurface.batchsvector3f_bufferoffset = 0;
7932         rsurface.batchtvector3f = NULL;
7933         rsurface.batchtvector3f_vertexbuffer = NULL;
7934         rsurface.batchtvector3f_bufferoffset = 0;
7935         rsurface.batchnormal3f  = NULL;
7936         rsurface.batchnormal3f_vertexbuffer = NULL;
7937         rsurface.batchnormal3f_bufferoffset = 0;
7938         rsurface.batchlightmapcolor4f = NULL;
7939         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7940         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7941         rsurface.batchtexcoordtexture2f = NULL;
7942         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7943         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7944         rsurface.batchtexcoordlightmap2f = NULL;
7945         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7946         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7947         rsurface.batchvertexmesh = NULL;
7948         rsurface.batchvertexmeshbuffer = NULL;
7949         rsurface.batchvertex3fbuffer = NULL;
7950         rsurface.batchelement3i = NULL;
7951         rsurface.batchelement3i_indexbuffer = NULL;
7952         rsurface.batchelement3i_bufferoffset = 0;
7953         rsurface.batchelement3s = NULL;
7954         rsurface.batchelement3s_indexbuffer = NULL;
7955         rsurface.batchelement3s_bufferoffset = 0;
7956         rsurface.passcolor4f = NULL;
7957         rsurface.passcolor4f_vertexbuffer = NULL;
7958         rsurface.passcolor4f_bufferoffset = 0;
7959 }
7960
7961 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7962 {
7963         dp_model_t *model = ent->model;
7964         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7965         //      return;
7966         rsurface.entity = (entity_render_t *)ent;
7967         rsurface.skeleton = ent->skeleton;
7968         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7969         rsurface.ent_skinnum = ent->skinnum;
7970         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;
7971         rsurface.ent_flags = ent->flags;
7972         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7973         rsurface.matrix = ent->matrix;
7974         rsurface.inversematrix = ent->inversematrix;
7975         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7976         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7977         R_EntityMatrix(&rsurface.matrix);
7978         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7979         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7980         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7981         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7982         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7983         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7984         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7985         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7986         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7987         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7988         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7989         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7990         rsurface.colormod[3] = ent->alpha;
7991         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7992         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7993         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7994         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7995         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7996         if (ent->model->brush.submodel && !prepass)
7997         {
7998                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7999                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8000         }
8001         if (model->surfmesh.isanimated && model->AnimateVertices)
8002         {
8003                 if (ent->animcache_vertex3f)
8004                 {
8005                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8006                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8007                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8008                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8009                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8010                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8011                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8012                 }
8013                 else if (wanttangents)
8014                 {
8015                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8016                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8017                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8018                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8019                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8020                         rsurface.modelvertexmesh = NULL;
8021                         rsurface.modelvertexmeshbuffer = NULL;
8022                         rsurface.modelvertex3fbuffer = NULL;
8023                 }
8024                 else if (wantnormals)
8025                 {
8026                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8027                         rsurface.modelsvector3f = NULL;
8028                         rsurface.modeltvector3f = NULL;
8029                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8030                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8031                         rsurface.modelvertexmesh = NULL;
8032                         rsurface.modelvertexmeshbuffer = NULL;
8033                         rsurface.modelvertex3fbuffer = NULL;
8034                 }
8035                 else
8036                 {
8037                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8038                         rsurface.modelsvector3f = NULL;
8039                         rsurface.modeltvector3f = NULL;
8040                         rsurface.modelnormal3f = NULL;
8041                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8042                         rsurface.modelvertexmesh = NULL;
8043                         rsurface.modelvertexmeshbuffer = NULL;
8044                         rsurface.modelvertex3fbuffer = NULL;
8045                 }
8046                 rsurface.modelvertex3f_vertexbuffer = 0;
8047                 rsurface.modelvertex3f_bufferoffset = 0;
8048                 rsurface.modelsvector3f_vertexbuffer = 0;
8049                 rsurface.modelsvector3f_bufferoffset = 0;
8050                 rsurface.modeltvector3f_vertexbuffer = 0;
8051                 rsurface.modeltvector3f_bufferoffset = 0;
8052                 rsurface.modelnormal3f_vertexbuffer = 0;
8053                 rsurface.modelnormal3f_bufferoffset = 0;
8054                 rsurface.modelgeneratedvertex = true;
8055         }
8056         else
8057         {
8058                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8059                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8061                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8062                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8064                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8065                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8067                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8068                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8070                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8071                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8072                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8073                 rsurface.modelgeneratedvertex = false;
8074         }
8075         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8076         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8078         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8079         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8081         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8082         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8084         rsurface.modelelement3i = model->surfmesh.data_element3i;
8085         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8086         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8087         rsurface.modelelement3s = model->surfmesh.data_element3s;
8088         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8089         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8090         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8091         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8092         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8093         rsurface.modelsurfaces = model->data_surfaces;
8094         rsurface.batchgeneratedvertex = false;
8095         rsurface.batchfirstvertex = 0;
8096         rsurface.batchnumvertices = 0;
8097         rsurface.batchfirsttriangle = 0;
8098         rsurface.batchnumtriangles = 0;
8099         rsurface.batchvertex3f  = NULL;
8100         rsurface.batchvertex3f_vertexbuffer = NULL;
8101         rsurface.batchvertex3f_bufferoffset = 0;
8102         rsurface.batchsvector3f = NULL;
8103         rsurface.batchsvector3f_vertexbuffer = NULL;
8104         rsurface.batchsvector3f_bufferoffset = 0;
8105         rsurface.batchtvector3f = NULL;
8106         rsurface.batchtvector3f_vertexbuffer = NULL;
8107         rsurface.batchtvector3f_bufferoffset = 0;
8108         rsurface.batchnormal3f  = NULL;
8109         rsurface.batchnormal3f_vertexbuffer = NULL;
8110         rsurface.batchnormal3f_bufferoffset = 0;
8111         rsurface.batchlightmapcolor4f = NULL;
8112         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8113         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8114         rsurface.batchtexcoordtexture2f = NULL;
8115         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8116         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8117         rsurface.batchtexcoordlightmap2f = NULL;
8118         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8119         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8120         rsurface.batchvertexmesh = NULL;
8121         rsurface.batchvertexmeshbuffer = NULL;
8122         rsurface.batchvertex3fbuffer = NULL;
8123         rsurface.batchelement3i = NULL;
8124         rsurface.batchelement3i_indexbuffer = NULL;
8125         rsurface.batchelement3i_bufferoffset = 0;
8126         rsurface.batchelement3s = NULL;
8127         rsurface.batchelement3s_indexbuffer = NULL;
8128         rsurface.batchelement3s_bufferoffset = 0;
8129         rsurface.passcolor4f = NULL;
8130         rsurface.passcolor4f_vertexbuffer = NULL;
8131         rsurface.passcolor4f_bufferoffset = 0;
8132 }
8133
8134 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)
8135 {
8136         rsurface.entity = r_refdef.scene.worldentity;
8137         rsurface.skeleton = NULL;
8138         rsurface.ent_skinnum = 0;
8139         rsurface.ent_qwskin = -1;
8140         rsurface.ent_flags = entflags;
8141         rsurface.shadertime = r_refdef.scene.time - shadertime;
8142         rsurface.modelnumvertices = numvertices;
8143         rsurface.modelnumtriangles = numtriangles;
8144         rsurface.matrix = *matrix;
8145         rsurface.inversematrix = *inversematrix;
8146         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8147         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8148         R_EntityMatrix(&rsurface.matrix);
8149         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8150         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8151         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8152         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8153         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8154         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8155         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8156         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8157         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8158         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8159         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8160         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8161         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);
8162         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8163         rsurface.frameblend[0].lerp = 1;
8164         rsurface.ent_alttextures = false;
8165         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8166         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8167         if (wanttangents)
8168         {
8169                 rsurface.modelvertex3f = (float *)vertex3f;
8170                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8171                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8172                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8173         }
8174         else if (wantnormals)
8175         {
8176                 rsurface.modelvertex3f = (float *)vertex3f;
8177                 rsurface.modelsvector3f = NULL;
8178                 rsurface.modeltvector3f = NULL;
8179                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8180         }
8181         else
8182         {
8183                 rsurface.modelvertex3f = (float *)vertex3f;
8184                 rsurface.modelsvector3f = NULL;
8185                 rsurface.modeltvector3f = NULL;
8186                 rsurface.modelnormal3f = NULL;
8187         }
8188         rsurface.modelvertexmesh = NULL;
8189         rsurface.modelvertexmeshbuffer = NULL;
8190         rsurface.modelvertex3fbuffer = NULL;
8191         rsurface.modelvertex3f_vertexbuffer = 0;
8192         rsurface.modelvertex3f_bufferoffset = 0;
8193         rsurface.modelsvector3f_vertexbuffer = 0;
8194         rsurface.modelsvector3f_bufferoffset = 0;
8195         rsurface.modeltvector3f_vertexbuffer = 0;
8196         rsurface.modeltvector3f_bufferoffset = 0;
8197         rsurface.modelnormal3f_vertexbuffer = 0;
8198         rsurface.modelnormal3f_bufferoffset = 0;
8199         rsurface.modelgeneratedvertex = true;
8200         rsurface.modellightmapcolor4f  = (float *)color4f;
8201         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8202         rsurface.modellightmapcolor4f_bufferoffset = 0;
8203         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8204         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8205         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8206         rsurface.modeltexcoordlightmap2f  = NULL;
8207         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8208         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8209         rsurface.modelelement3i = (int *)element3i;
8210         rsurface.modelelement3i_indexbuffer = NULL;
8211         rsurface.modelelement3i_bufferoffset = 0;
8212         rsurface.modelelement3s = (unsigned short *)element3s;
8213         rsurface.modelelement3s_indexbuffer = NULL;
8214         rsurface.modelelement3s_bufferoffset = 0;
8215         rsurface.modellightmapoffsets = NULL;
8216         rsurface.modelsurfaces = NULL;
8217         rsurface.batchgeneratedvertex = false;
8218         rsurface.batchfirstvertex = 0;
8219         rsurface.batchnumvertices = 0;
8220         rsurface.batchfirsttriangle = 0;
8221         rsurface.batchnumtriangles = 0;
8222         rsurface.batchvertex3f  = NULL;
8223         rsurface.batchvertex3f_vertexbuffer = NULL;
8224         rsurface.batchvertex3f_bufferoffset = 0;
8225         rsurface.batchsvector3f = NULL;
8226         rsurface.batchsvector3f_vertexbuffer = NULL;
8227         rsurface.batchsvector3f_bufferoffset = 0;
8228         rsurface.batchtvector3f = NULL;
8229         rsurface.batchtvector3f_vertexbuffer = NULL;
8230         rsurface.batchtvector3f_bufferoffset = 0;
8231         rsurface.batchnormal3f  = NULL;
8232         rsurface.batchnormal3f_vertexbuffer = NULL;
8233         rsurface.batchnormal3f_bufferoffset = 0;
8234         rsurface.batchlightmapcolor4f = NULL;
8235         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8236         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8237         rsurface.batchtexcoordtexture2f = NULL;
8238         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8239         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8240         rsurface.batchtexcoordlightmap2f = NULL;
8241         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8242         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8243         rsurface.batchvertexmesh = NULL;
8244         rsurface.batchvertexmeshbuffer = NULL;
8245         rsurface.batchvertex3fbuffer = NULL;
8246         rsurface.batchelement3i = NULL;
8247         rsurface.batchelement3i_indexbuffer = NULL;
8248         rsurface.batchelement3i_bufferoffset = 0;
8249         rsurface.batchelement3s = NULL;
8250         rsurface.batchelement3s_indexbuffer = NULL;
8251         rsurface.batchelement3s_bufferoffset = 0;
8252         rsurface.passcolor4f = NULL;
8253         rsurface.passcolor4f_vertexbuffer = NULL;
8254         rsurface.passcolor4f_bufferoffset = 0;
8255
8256         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8257         {
8258                 if ((wantnormals || wanttangents) && !normal3f)
8259                 {
8260                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8261                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8262                 }
8263                 if (wanttangents && !svector3f)
8264                 {
8265                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8266                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8267                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8268                 }
8269         }
8270 }
8271
8272 float RSurf_FogPoint(const float *v)
8273 {
8274         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8275         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8276         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8277         float FogHeightFade = r_refdef.fogheightfade;
8278         float fogfrac;
8279         unsigned int fogmasktableindex;
8280         if (r_refdef.fogplaneviewabove)
8281                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8282         else
8283                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8284         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8285         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8286 }
8287
8288 float RSurf_FogVertex(const float *v)
8289 {
8290         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8291         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8292         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8293         float FogHeightFade = rsurface.fogheightfade;
8294         float fogfrac;
8295         unsigned int fogmasktableindex;
8296         if (r_refdef.fogplaneviewabove)
8297                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8298         else
8299                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8300         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8301         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8302 }
8303
8304 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8305 {
8306         int i;
8307         for (i = 0;i < numelements;i++)
8308                 outelement3i[i] = inelement3i[i] + adjust;
8309 }
8310
8311 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8312 extern cvar_t gl_vbo;
8313 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8314 {
8315         int deformindex;
8316         int firsttriangle;
8317         int numtriangles;
8318         int firstvertex;
8319         int endvertex;
8320         int numvertices;
8321         int surfacefirsttriangle;
8322         int surfacenumtriangles;
8323         int surfacefirstvertex;
8324         int surfaceendvertex;
8325         int surfacenumvertices;
8326         int batchnumvertices;
8327         int batchnumtriangles;
8328         int needsupdate;
8329         int i, j;
8330         qboolean gaps;
8331         qboolean dynamicvertex;
8332         float amplitude;
8333         float animpos;
8334         float scale;
8335         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8336         float waveparms[4];
8337         q3shaderinfo_deform_t *deform;
8338         const msurface_t *surface, *firstsurface;
8339         r_vertexmesh_t *vertexmesh;
8340         if (!texturenumsurfaces)
8341                 return;
8342         // find vertex range of this surface batch
8343         gaps = false;
8344         firstsurface = texturesurfacelist[0];
8345         firsttriangle = firstsurface->num_firsttriangle;
8346         batchnumvertices = 0;
8347         batchnumtriangles = 0;
8348         firstvertex = endvertex = firstsurface->num_firstvertex;
8349         for (i = 0;i < texturenumsurfaces;i++)
8350         {
8351                 surface = texturesurfacelist[i];
8352                 if (surface != firstsurface + i)
8353                         gaps = true;
8354                 surfacefirstvertex = surface->num_firstvertex;
8355                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8356                 surfacenumvertices = surface->num_vertices;
8357                 surfacenumtriangles = surface->num_triangles;
8358                 if (firstvertex > surfacefirstvertex)
8359                         firstvertex = surfacefirstvertex;
8360                 if (endvertex < surfaceendvertex)
8361                         endvertex = surfaceendvertex;
8362                 batchnumvertices += surfacenumvertices;
8363                 batchnumtriangles += surfacenumtriangles;
8364         }
8365
8366         // we now know the vertex range used, and if there are any gaps in it
8367         rsurface.batchfirstvertex = firstvertex;
8368         rsurface.batchnumvertices = endvertex - firstvertex;
8369         rsurface.batchfirsttriangle = firsttriangle;
8370         rsurface.batchnumtriangles = batchnumtriangles;
8371
8372         // this variable holds flags for which properties have been updated that
8373         // may require regenerating vertexmesh array...
8374         needsupdate = 0;
8375
8376         // check if any dynamic vertex processing must occur
8377         dynamicvertex = false;
8378
8379         // if there is a chance of animated vertex colors, it's a dynamic batch
8380         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8381         {
8382                 dynamicvertex = true;
8383                 batchneed |= BATCHNEED_NOGAPS;
8384                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8385         }
8386
8387         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8388         {
8389                 switch (deform->deform)
8390                 {
8391                 default:
8392                 case Q3DEFORM_PROJECTIONSHADOW:
8393                 case Q3DEFORM_TEXT0:
8394                 case Q3DEFORM_TEXT1:
8395                 case Q3DEFORM_TEXT2:
8396                 case Q3DEFORM_TEXT3:
8397                 case Q3DEFORM_TEXT4:
8398                 case Q3DEFORM_TEXT5:
8399                 case Q3DEFORM_TEXT6:
8400                 case Q3DEFORM_TEXT7:
8401                 case Q3DEFORM_NONE:
8402                         break;
8403                 case Q3DEFORM_AUTOSPRITE:
8404                         dynamicvertex = true;
8405                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8406                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8407                         break;
8408                 case Q3DEFORM_AUTOSPRITE2:
8409                         dynamicvertex = true;
8410                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8411                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8412                         break;
8413                 case Q3DEFORM_NORMAL:
8414                         dynamicvertex = true;
8415                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8416                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8417                         break;
8418                 case Q3DEFORM_WAVE:
8419                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8420                                 break; // if wavefunc is a nop, ignore this transform
8421                         dynamicvertex = true;
8422                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8423                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8424                         break;
8425                 case Q3DEFORM_BULGE:
8426                         dynamicvertex = true;
8427                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8428                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8429                         break;
8430                 case Q3DEFORM_MOVE:
8431                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8432                                 break; // if wavefunc is a nop, ignore this transform
8433                         dynamicvertex = true;
8434                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8435                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8436                         break;
8437                 }
8438         }
8439         switch(rsurface.texture->tcgen.tcgen)
8440         {
8441         default:
8442         case Q3TCGEN_TEXTURE:
8443                 break;
8444         case Q3TCGEN_LIGHTMAP:
8445                 dynamicvertex = true;
8446                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8447                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8448                 break;
8449         case Q3TCGEN_VECTOR:
8450                 dynamicvertex = true;
8451                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8452                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8453                 break;
8454         case Q3TCGEN_ENVIRONMENT:
8455                 dynamicvertex = true;
8456                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8457                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8458                 break;
8459         }
8460         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8461         {
8462                 dynamicvertex = true;
8463                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8464                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8465         }
8466
8467         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8468         {
8469                 dynamicvertex = true;
8470                 batchneed |= BATCHNEED_NOGAPS;
8471                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8472         }
8473
8474         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8475         {
8476                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8477                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8478                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8479                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8480                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8481                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8482                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8483         }
8484
8485         // when the model data has no vertex buffer (dynamic mesh), we need to
8486         // eliminate gaps
8487         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8488                 batchneed |= BATCHNEED_NOGAPS;
8489
8490         // if needsupdate, we have to do a dynamic vertex batch for sure
8491         if (needsupdate & batchneed)
8492                 dynamicvertex = true;
8493
8494         // see if we need to build vertexmesh from arrays
8495         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8496                 dynamicvertex = true;
8497
8498         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8499         // also some drivers strongly dislike firstvertex
8500         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8501                 dynamicvertex = true;
8502
8503         rsurface.batchvertex3f = rsurface.modelvertex3f;
8504         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8505         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8506         rsurface.batchsvector3f = rsurface.modelsvector3f;
8507         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8508         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8509         rsurface.batchtvector3f = rsurface.modeltvector3f;
8510         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8511         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8512         rsurface.batchnormal3f = rsurface.modelnormal3f;
8513         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8514         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8515         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8516         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8517         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8518         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8519         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8520         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8521         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8522         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8523         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8524         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8525         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8526         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8527         rsurface.batchelement3i = rsurface.modelelement3i;
8528         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8529         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8530         rsurface.batchelement3s = rsurface.modelelement3s;
8531         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8532         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8533
8534         // if any dynamic vertex processing has to occur in software, we copy the
8535         // entire surface list together before processing to rebase the vertices
8536         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8537         //
8538         // if any gaps exist and we do not have a static vertex buffer, we have to
8539         // copy the surface list together to avoid wasting upload bandwidth on the
8540         // vertices in the gaps.
8541         //
8542         // if gaps exist and we have a static vertex buffer, we still have to
8543         // combine the index buffer ranges into one dynamic index buffer.
8544         //
8545         // in all cases we end up with data that can be drawn in one call.
8546
8547         if (!dynamicvertex)
8548         {
8549                 // static vertex data, just set pointers...
8550                 rsurface.batchgeneratedvertex = false;
8551                 // if there are gaps, we want to build a combined index buffer,
8552                 // otherwise use the original static buffer with an appropriate offset
8553                 if (gaps)
8554                 {
8555                         // build a new triangle elements array for this batch
8556                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8557                         rsurface.batchfirsttriangle = 0;
8558                         numtriangles = 0;
8559                         for (i = 0;i < texturenumsurfaces;i++)
8560                         {
8561                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8562                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8563                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8564                                 numtriangles += surfacenumtriangles;
8565                         }
8566                         rsurface.batchelement3i_indexbuffer = NULL;
8567                         rsurface.batchelement3i_bufferoffset = 0;
8568                         rsurface.batchelement3s = NULL;
8569                         rsurface.batchelement3s_indexbuffer = NULL;
8570                         rsurface.batchelement3s_bufferoffset = 0;
8571                         if (endvertex <= 65536)
8572                         {
8573                                 // make a 16bit (unsigned short) index array if possible
8574                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575                                 for (i = 0;i < numtriangles*3;i++)
8576                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8577                         }
8578                 }
8579                 return;
8580         }
8581
8582         // something needs software processing, do it for real...
8583         // we only directly handle separate array data in this case and then
8584         // generate interleaved data if needed...
8585         rsurface.batchgeneratedvertex = true;
8586
8587         // now copy the vertex data into a combined array and make an index array
8588         // (this is what Quake3 does all the time)
8589         //if (gaps || rsurface.batchfirstvertex)
8590         {
8591                 rsurface.batchvertex3fbuffer = NULL;
8592                 rsurface.batchvertexmesh = NULL;
8593                 rsurface.batchvertexmeshbuffer = NULL;
8594                 rsurface.batchvertex3f = NULL;
8595                 rsurface.batchvertex3f_vertexbuffer = NULL;
8596                 rsurface.batchvertex3f_bufferoffset = 0;
8597                 rsurface.batchsvector3f = NULL;
8598                 rsurface.batchsvector3f_vertexbuffer = NULL;
8599                 rsurface.batchsvector3f_bufferoffset = 0;
8600                 rsurface.batchtvector3f = NULL;
8601                 rsurface.batchtvector3f_vertexbuffer = NULL;
8602                 rsurface.batchtvector3f_bufferoffset = 0;
8603                 rsurface.batchnormal3f = NULL;
8604                 rsurface.batchnormal3f_vertexbuffer = NULL;
8605                 rsurface.batchnormal3f_bufferoffset = 0;
8606                 rsurface.batchlightmapcolor4f = NULL;
8607                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8608                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8609                 rsurface.batchtexcoordtexture2f = NULL;
8610                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8611                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8612                 rsurface.batchtexcoordlightmap2f = NULL;
8613                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8614                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8615                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8616                 rsurface.batchelement3i_indexbuffer = NULL;
8617                 rsurface.batchelement3i_bufferoffset = 0;
8618                 rsurface.batchelement3s = NULL;
8619                 rsurface.batchelement3s_indexbuffer = NULL;
8620                 rsurface.batchelement3s_bufferoffset = 0;
8621                 // we'll only be setting up certain arrays as needed
8622                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8623                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8624                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8625                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8626                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8627                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8628                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8629                 {
8630                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8631                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8632                 }
8633                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8634                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8635                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8636                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8637                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8638                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8639                 numvertices = 0;
8640                 numtriangles = 0;
8641                 for (i = 0;i < texturenumsurfaces;i++)
8642                 {
8643                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8644                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8645                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8646                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8647                         // copy only the data requested
8648                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8649                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8650                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8651                         {
8652                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8653                                 {
8654                                         if (rsurface.batchvertex3f)
8655                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8656                                         else
8657                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8658                                 }
8659                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8660                                 {
8661                                         if (rsurface.modelnormal3f)
8662                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8663                                         else
8664                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8665                                 }
8666                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8667                                 {
8668                                         if (rsurface.modelsvector3f)
8669                                         {
8670                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8671                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8672                                         }
8673                                         else
8674                                         {
8675                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8676                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8677                                         }
8678                                 }
8679                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8680                                 {
8681                                         if (rsurface.modellightmapcolor4f)
8682                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8683                                         else
8684                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8685                                 }
8686                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8687                                 {
8688                                         if (rsurface.modeltexcoordtexture2f)
8689                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8690                                         else
8691                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8692                                 }
8693                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8694                                 {
8695                                         if (rsurface.modeltexcoordlightmap2f)
8696                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8697                                         else
8698                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8699                                 }
8700                         }
8701                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8702                         numvertices += surfacenumvertices;
8703                         numtriangles += surfacenumtriangles;
8704                 }
8705
8706                 // generate a 16bit index array as well if possible
8707                 // (in general, dynamic batches fit)
8708                 if (numvertices <= 65536)
8709                 {
8710                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8711                         for (i = 0;i < numtriangles*3;i++)
8712                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8713                 }
8714
8715                 // since we've copied everything, the batch now starts at 0
8716                 rsurface.batchfirstvertex = 0;
8717                 rsurface.batchnumvertices = batchnumvertices;
8718                 rsurface.batchfirsttriangle = 0;
8719                 rsurface.batchnumtriangles = batchnumtriangles;
8720         }
8721
8722         // q1bsp surfaces rendered in vertex color mode have to have colors
8723         // calculated based on lightstyles
8724         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8725         {
8726                 // generate color arrays for the surfaces in this list
8727                 int c[4];
8728                 int scale;
8729                 int size3;
8730                 const int *offsets;
8731                 const unsigned char *lm;
8732                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8733                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8734                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8735                 numvertices = 0;
8736                 for (i = 0;i < texturenumsurfaces;i++)
8737                 {
8738                         surface = texturesurfacelist[i];
8739                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8740                         surfacenumvertices = surface->num_vertices;
8741                         if (surface->lightmapinfo->samples)
8742                         {
8743                                 for (j = 0;j < surfacenumvertices;j++)
8744                                 {
8745                                         lm = surface->lightmapinfo->samples + offsets[j];
8746                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8747                                         VectorScale(lm, scale, c);
8748                                         if (surface->lightmapinfo->styles[1] != 255)
8749                                         {
8750                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8751                                                 lm += size3;
8752                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8753                                                 VectorMA(c, scale, lm, c);
8754                                                 if (surface->lightmapinfo->styles[2] != 255)
8755                                                 {
8756                                                         lm += size3;
8757                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8758                                                         VectorMA(c, scale, lm, c);
8759                                                         if (surface->lightmapinfo->styles[3] != 255)
8760                                                         {
8761                                                                 lm += size3;
8762                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8763                                                                 VectorMA(c, scale, lm, c);
8764                                                         }
8765                                                 }
8766                                         }
8767                                         c[0] >>= 7;
8768                                         c[1] >>= 7;
8769                                         c[2] >>= 7;
8770                                         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);
8771                                         numvertices++;
8772                                 }
8773                         }
8774                         else
8775                         {
8776                                 for (j = 0;j < surfacenumvertices;j++)
8777                                 {
8778                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8779                                         numvertices++;
8780                                 }
8781                         }
8782                 }
8783         }
8784
8785         // if vertices are deformed (sprite flares and things in maps, possibly
8786         // water waves, bulges and other deformations), modify the copied vertices
8787         // in place
8788         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8789         {
8790                 switch (deform->deform)
8791                 {
8792                 default:
8793                 case Q3DEFORM_PROJECTIONSHADOW:
8794                 case Q3DEFORM_TEXT0:
8795                 case Q3DEFORM_TEXT1:
8796                 case Q3DEFORM_TEXT2:
8797                 case Q3DEFORM_TEXT3:
8798                 case Q3DEFORM_TEXT4:
8799                 case Q3DEFORM_TEXT5:
8800                 case Q3DEFORM_TEXT6:
8801                 case Q3DEFORM_TEXT7:
8802                 case Q3DEFORM_NONE:
8803                         break;
8804                 case Q3DEFORM_AUTOSPRITE:
8805                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8806                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8807                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8808                         VectorNormalize(newforward);
8809                         VectorNormalize(newright);
8810                         VectorNormalize(newup);
8811 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8812 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8813 //                      rsurface.batchvertex3f_bufferoffset = 0;
8814 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8815 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8816 //                      rsurface.batchsvector3f_bufferoffset = 0;
8817 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8818 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8819 //                      rsurface.batchtvector3f_bufferoffset = 0;
8820 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8821 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8822 //                      rsurface.batchnormal3f_bufferoffset = 0;
8823                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8824                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8825                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8826                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8827                                 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);
8828                         // a single autosprite surface can contain multiple sprites...
8829                         for (j = 0;j < batchnumvertices - 3;j += 4)
8830                         {
8831                                 VectorClear(center);
8832                                 for (i = 0;i < 4;i++)
8833                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8834                                 VectorScale(center, 0.25f, center);
8835                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8836                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8837                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8838                                 for (i = 0;i < 4;i++)
8839                                 {
8840                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8841                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8842                                 }
8843                         }
8844                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8845                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8846                         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);
8847                         break;
8848                 case Q3DEFORM_AUTOSPRITE2:
8849                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8850                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8851                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8852                         VectorNormalize(newforward);
8853                         VectorNormalize(newright);
8854                         VectorNormalize(newup);
8855 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8856 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8857 //                      rsurface.batchvertex3f_bufferoffset = 0;
8858                         {
8859                                 const float *v1, *v2;
8860                                 vec3_t start, end;
8861                                 float f, l;
8862                                 struct
8863                                 {
8864                                         float length2;
8865                                         const float *v1;
8866                                         const float *v2;
8867                                 }
8868                                 shortest[2];
8869                                 memset(shortest, 0, sizeof(shortest));
8870                                 // a single autosprite surface can contain multiple sprites...
8871                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8872                                 {
8873                                         VectorClear(center);
8874                                         for (i = 0;i < 4;i++)
8875                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8876                                         VectorScale(center, 0.25f, center);
8877                                         // find the two shortest edges, then use them to define the
8878                                         // axis vectors for rotating around the central axis
8879                                         for (i = 0;i < 6;i++)
8880                                         {
8881                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8882                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8883                                                 l = VectorDistance2(v1, v2);
8884                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8885                                                 if (v1[2] != v2[2])
8886                                                         l += (1.0f / 1024.0f);
8887                                                 if (shortest[0].length2 > l || i == 0)
8888                                                 {
8889                                                         shortest[1] = shortest[0];
8890                                                         shortest[0].length2 = l;
8891                                                         shortest[0].v1 = v1;
8892                                                         shortest[0].v2 = v2;
8893                                                 }
8894                                                 else if (shortest[1].length2 > l || i == 1)
8895                                                 {
8896                                                         shortest[1].length2 = l;
8897                                                         shortest[1].v1 = v1;
8898                                                         shortest[1].v2 = v2;
8899                                                 }
8900                                         }
8901                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8902                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8903                                         // this calculates the right vector from the shortest edge
8904                                         // and the up vector from the edge midpoints
8905                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8906                                         VectorNormalize(right);
8907                                         VectorSubtract(end, start, up);
8908                                         VectorNormalize(up);
8909                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8910                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8911                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8912                                         VectorNegate(forward, forward);
8913                                         VectorReflect(forward, 0, up, forward);
8914                                         VectorNormalize(forward);
8915                                         CrossProduct(up, forward, newright);
8916                                         VectorNormalize(newright);
8917                                         // rotate the quad around the up axis vector, this is made
8918                                         // especially easy by the fact we know the quad is flat,
8919                                         // so we only have to subtract the center position and
8920                                         // measure distance along the right vector, and then
8921                                         // multiply that by the newright vector and add back the
8922                                         // center position
8923                                         // we also need to subtract the old position to undo the
8924                                         // displacement from the center, which we do with a
8925                                         // DotProduct, the subtraction/addition of center is also
8926                                         // optimized into DotProducts here
8927                                         l = DotProduct(right, center);
8928                                         for (i = 0;i < 4;i++)
8929                                         {
8930                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8931                                                 f = DotProduct(right, v1) - l;
8932                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8933                                         }
8934                                 }
8935                         }
8936                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8937                         {
8938 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8939 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8940 //                              rsurface.batchnormal3f_bufferoffset = 0;
8941                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8942                         }
8943                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8944                         {
8945 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8946 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8947 //                              rsurface.batchsvector3f_bufferoffset = 0;
8948 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8949 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8950 //                              rsurface.batchtvector3f_bufferoffset = 0;
8951                                 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);
8952                         }
8953                         break;
8954                 case Q3DEFORM_NORMAL:
8955                         // deform the normals to make reflections wavey
8956                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8957                         rsurface.batchnormal3f_vertexbuffer = NULL;
8958                         rsurface.batchnormal3f_bufferoffset = 0;
8959                         for (j = 0;j < batchnumvertices;j++)
8960                         {
8961                                 float vertex[3];
8962                                 float *normal = rsurface.batchnormal3f + 3*j;
8963                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8964                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8965                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8966                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8967                                 VectorNormalize(normal);
8968                         }
8969                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8970                         {
8971 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8972 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8973 //                              rsurface.batchsvector3f_bufferoffset = 0;
8974 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8975 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8976 //                              rsurface.batchtvector3f_bufferoffset = 0;
8977                                 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);
8978                         }
8979                         break;
8980                 case Q3DEFORM_WAVE:
8981                         // deform vertex array to make wavey water and flags and such
8982                         waveparms[0] = deform->waveparms[0];
8983                         waveparms[1] = deform->waveparms[1];
8984                         waveparms[2] = deform->waveparms[2];
8985                         waveparms[3] = deform->waveparms[3];
8986                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8987                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8988                         // this is how a divisor of vertex influence on deformation
8989                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8990                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8991 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8992 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8993 //                      rsurface.batchvertex3f_bufferoffset = 0;
8994 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8995 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8996 //                      rsurface.batchnormal3f_bufferoffset = 0;
8997                         for (j = 0;j < batchnumvertices;j++)
8998                         {
8999                                 // if the wavefunc depends on time, evaluate it per-vertex
9000                                 if (waveparms[3])
9001                                 {
9002                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9003                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9004                                 }
9005                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9006                         }
9007                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9008                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9009                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9010                         {
9011 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9012 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9013 //                              rsurface.batchsvector3f_bufferoffset = 0;
9014 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9015 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9016 //                              rsurface.batchtvector3f_bufferoffset = 0;
9017                                 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);
9018                         }
9019                         break;
9020                 case Q3DEFORM_BULGE:
9021                         // deform vertex array to make the surface have moving bulges
9022 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9023 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9024 //                      rsurface.batchvertex3f_bufferoffset = 0;
9025 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9026 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9027 //                      rsurface.batchnormal3f_bufferoffset = 0;
9028                         for (j = 0;j < batchnumvertices;j++)
9029                         {
9030                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9031                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9032                         }
9033                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9034                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9035                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9036                         {
9037 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9038 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9039 //                              rsurface.batchsvector3f_bufferoffset = 0;
9040 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9041 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9042 //                              rsurface.batchtvector3f_bufferoffset = 0;
9043                                 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);
9044                         }
9045                         break;
9046                 case Q3DEFORM_MOVE:
9047                         // deform vertex array
9048                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9049                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9050                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9051                         VectorScale(deform->parms, scale, waveparms);
9052 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9053 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9054 //                      rsurface.batchvertex3f_bufferoffset = 0;
9055                         for (j = 0;j < batchnumvertices;j++)
9056                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9057                         break;
9058                 }
9059         }
9060
9061         // generate texcoords based on the chosen texcoord source
9062         switch(rsurface.texture->tcgen.tcgen)
9063         {
9064         default:
9065         case Q3TCGEN_TEXTURE:
9066                 break;
9067         case Q3TCGEN_LIGHTMAP:
9068 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9069 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9070 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9071                 if (rsurface.batchtexcoordlightmap2f)
9072                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9073                 break;
9074         case Q3TCGEN_VECTOR:
9075 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9076 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9077 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9078                 for (j = 0;j < batchnumvertices;j++)
9079                 {
9080                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9081                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9082                 }
9083                 break;
9084         case Q3TCGEN_ENVIRONMENT:
9085                 // make environment reflections using a spheremap
9086                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9087                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9088                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9089                 for (j = 0;j < batchnumvertices;j++)
9090                 {
9091                         // identical to Q3A's method, but executed in worldspace so
9092                         // carried models can be shiny too
9093
9094                         float viewer[3], d, reflected[3], worldreflected[3];
9095
9096                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9097                         // VectorNormalize(viewer);
9098
9099                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9100
9101                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9102                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9103                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9104                         // note: this is proportinal to viewer, so we can normalize later
9105
9106                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9107                         VectorNormalize(worldreflected);
9108
9109                         // note: this sphere map only uses world x and z!
9110                         // so positive and negative y will LOOK THE SAME.
9111                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9112                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9113                 }
9114                 break;
9115         }
9116         // the only tcmod that needs software vertex processing is turbulent, so
9117         // check for it here and apply the changes if needed
9118         // and we only support that as the first one
9119         // (handling a mixture of turbulent and other tcmods would be problematic
9120         //  without punting it entirely to a software path)
9121         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9122         {
9123                 amplitude = rsurface.texture->tcmods[0].parms[1];
9124                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9125 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9126 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9127 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9128                 for (j = 0;j < batchnumvertices;j++)
9129                 {
9130                         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);
9131                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9132                 }
9133         }
9134
9135         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9136         {
9137                 // convert the modified arrays to vertex structs
9138 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9139 //              rsurface.batchvertexmeshbuffer = NULL;
9140                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9141                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9142                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9143                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9144                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9145                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9146                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9147                 {
9148                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9149                         {
9150                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9151                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9152                         }
9153                 }
9154                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9155                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9156                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9157                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9158                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9159                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9160                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9161                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9162                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9163         }
9164 }
9165
9166 void RSurf_DrawBatch(void)
9167 {
9168         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9169         // through the pipeline, killing it earlier in the pipeline would have
9170         // per-surface overhead rather than per-batch overhead, so it's best to
9171         // reject it here, before it hits glDraw.
9172         if (rsurface.batchnumtriangles == 0)
9173                 return;
9174 #if 0
9175         // batch debugging code
9176         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9177         {
9178                 int i;
9179                 int j;
9180                 int c;
9181                 const int *e;
9182                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9183                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9184                 {
9185                         c = e[i];
9186                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9187                         {
9188                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9189                                 {
9190                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9191                                                 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);
9192                                         break;
9193                                 }
9194                         }
9195                 }
9196         }
9197 #endif
9198         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);
9199 }
9200
9201 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9202 {
9203         // pick the closest matching water plane
9204         int planeindex, vertexindex, bestplaneindex = -1;
9205         float d, bestd;
9206         vec3_t vert;
9207         const float *v;
9208         r_waterstate_waterplane_t *p;
9209         qboolean prepared = false;
9210         bestd = 0;
9211         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9212         {
9213                 if(p->camera_entity != rsurface.texture->camera_entity)
9214                         continue;
9215                 d = 0;
9216                 if(!prepared)
9217                 {
9218                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9219                         prepared = true;
9220                         if(rsurface.batchnumvertices == 0)
9221                                 break;
9222                 }
9223                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9224                 {
9225                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9226                         d += fabs(PlaneDiff(vert, &p->plane));
9227                 }
9228                 if (bestd > d || bestplaneindex < 0)
9229                 {
9230                         bestd = d;
9231                         bestplaneindex = planeindex;
9232                 }
9233         }
9234         return bestplaneindex;
9235         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9236         // this situation though, as it might be better to render single larger
9237         // batches with useless stuff (backface culled for example) than to
9238         // render multiple smaller batches
9239 }
9240
9241 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9242 {
9243         int i;
9244         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9245         rsurface.passcolor4f_vertexbuffer = 0;
9246         rsurface.passcolor4f_bufferoffset = 0;
9247         for (i = 0;i < rsurface.batchnumvertices;i++)
9248                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9249 }
9250
9251 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9252 {
9253         int i;
9254         float f;
9255         const float *v;
9256         const float *c;
9257         float *c2;
9258         if (rsurface.passcolor4f)
9259         {
9260                 // generate color arrays
9261                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9262                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9263                 rsurface.passcolor4f_vertexbuffer = 0;
9264                 rsurface.passcolor4f_bufferoffset = 0;
9265                 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)
9266                 {
9267                         f = RSurf_FogVertex(v);
9268                         c2[0] = c[0] * f;
9269                         c2[1] = c[1] * f;
9270                         c2[2] = c[2] * f;
9271                         c2[3] = c[3];
9272                 }
9273         }
9274         else
9275         {
9276                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9277                 rsurface.passcolor4f_vertexbuffer = 0;
9278                 rsurface.passcolor4f_bufferoffset = 0;
9279                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9280                 {
9281                         f = RSurf_FogVertex(v);
9282                         c2[0] = f;
9283                         c2[1] = f;
9284                         c2[2] = f;
9285                         c2[3] = 1;
9286                 }
9287         }
9288 }
9289
9290 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9291 {
9292         int i;
9293         float f;
9294         const float *v;
9295         const float *c;
9296         float *c2;
9297         if (!rsurface.passcolor4f)
9298                 return;
9299         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9300         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9301         rsurface.passcolor4f_vertexbuffer = 0;
9302         rsurface.passcolor4f_bufferoffset = 0;
9303         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)
9304         {
9305                 f = RSurf_FogVertex(v);
9306                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9307                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9308                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9309                 c2[3] = c[3];
9310         }
9311 }
9312
9313 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9314 {
9315         int i;
9316         const float *c;
9317         float *c2;
9318         if (!rsurface.passcolor4f)
9319                 return;
9320         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9321         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9322         rsurface.passcolor4f_vertexbuffer = 0;
9323         rsurface.passcolor4f_bufferoffset = 0;
9324         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9325         {
9326                 c2[0] = c[0] * r;
9327                 c2[1] = c[1] * g;
9328                 c2[2] = c[2] * b;
9329                 c2[3] = c[3] * a;
9330         }
9331 }
9332
9333 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9334 {
9335         int i;
9336         const float *c;
9337         float *c2;
9338         if (!rsurface.passcolor4f)
9339                 return;
9340         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9341         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9342         rsurface.passcolor4f_vertexbuffer = 0;
9343         rsurface.passcolor4f_bufferoffset = 0;
9344         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9345         {
9346                 c2[0] = c[0] + r_refdef.scene.ambient;
9347                 c2[1] = c[1] + r_refdef.scene.ambient;
9348                 c2[2] = c[2] + r_refdef.scene.ambient;
9349                 c2[3] = c[3];
9350         }
9351 }
9352
9353 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9354 {
9355         // TODO: optimize
9356         rsurface.passcolor4f = NULL;
9357         rsurface.passcolor4f_vertexbuffer = 0;
9358         rsurface.passcolor4f_bufferoffset = 0;
9359         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9360         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9361         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9362         GL_Color(r, g, b, a);
9363         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9364         RSurf_DrawBatch();
9365 }
9366
9367 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9368 {
9369         // TODO: optimize applyfog && applycolor case
9370         // just apply fog if necessary, and tint the fog color array if necessary
9371         rsurface.passcolor4f = NULL;
9372         rsurface.passcolor4f_vertexbuffer = 0;
9373         rsurface.passcolor4f_bufferoffset = 0;
9374         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9375         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9376         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9377         GL_Color(r, g, b, a);
9378         RSurf_DrawBatch();
9379 }
9380
9381 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9382 {
9383         // TODO: optimize
9384         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9385         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9386         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9387         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9388         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9389         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9390         GL_Color(r, g, b, a);
9391         RSurf_DrawBatch();
9392 }
9393
9394 static void RSurf_DrawBatch_GL11_ClampColor(void)
9395 {
9396         int i;
9397         const float *c1;
9398         float *c2;
9399         if (!rsurface.passcolor4f)
9400                 return;
9401         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9402         {
9403                 c2[0] = bound(0.0f, c1[0], 1.0f);
9404                 c2[1] = bound(0.0f, c1[1], 1.0f);
9405                 c2[2] = bound(0.0f, c1[2], 1.0f);
9406                 c2[3] = bound(0.0f, c1[3], 1.0f);
9407         }
9408 }
9409
9410 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9411 {
9412         int i;
9413         float f;
9414         const float *v;
9415         const float *n;
9416         float *c;
9417         //vec3_t eyedir;
9418
9419         // fake shading
9420         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9421         rsurface.passcolor4f_vertexbuffer = 0;
9422         rsurface.passcolor4f_bufferoffset = 0;
9423         for (i = 0, 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)
9424         {
9425                 f = -DotProduct(r_refdef.view.forward, n);
9426                 f = max(0, f);
9427                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9428                 f *= r_refdef.lightmapintensity;
9429                 Vector4Set(c, f, f, f, 1);
9430         }
9431 }
9432
9433 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9434 {
9435         RSurf_DrawBatch_GL11_ApplyFakeLight();
9436         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9437         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9438         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9439         GL_Color(r, g, b, a);
9440         RSurf_DrawBatch();
9441 }
9442
9443 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9444 {
9445         int i;
9446         float f;
9447         float alpha;
9448         const float *v;
9449         const float *n;
9450         float *c;
9451         vec3_t ambientcolor;
9452         vec3_t diffusecolor;
9453         vec3_t lightdir;
9454         // TODO: optimize
9455         // model lighting
9456         VectorCopy(rsurface.modellight_lightdir, lightdir);
9457         f = 0.5f * r_refdef.lightmapintensity;
9458         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9459         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9460         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9461         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9462         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9463         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9464         alpha = *a;
9465         if (VectorLength2(diffusecolor) > 0)
9466         {
9467                 // q3-style directional shading
9468                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9469                 rsurface.passcolor4f_vertexbuffer = 0;
9470                 rsurface.passcolor4f_bufferoffset = 0;
9471                 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)
9472                 {
9473                         if ((f = DotProduct(n, lightdir)) > 0)
9474                                 VectorMA(ambientcolor, f, diffusecolor, c);
9475                         else
9476                                 VectorCopy(ambientcolor, c);
9477                         c[3] = alpha;
9478                 }
9479                 *r = 1;
9480                 *g = 1;
9481                 *b = 1;
9482                 *a = 1;
9483                 *applycolor = false;
9484         }
9485         else
9486         {
9487                 *r = ambientcolor[0];
9488                 *g = ambientcolor[1];
9489                 *b = ambientcolor[2];
9490                 rsurface.passcolor4f = NULL;
9491                 rsurface.passcolor4f_vertexbuffer = 0;
9492                 rsurface.passcolor4f_bufferoffset = 0;
9493         }
9494 }
9495
9496 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9497 {
9498         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9499         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9500         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9501         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9502         GL_Color(r, g, b, a);
9503         RSurf_DrawBatch();
9504 }
9505
9506 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9507 {
9508         int i;
9509         float f;
9510         const float *v;
9511         float *c;
9512
9513         // fake shading
9514         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9515         rsurface.passcolor4f_vertexbuffer = 0;
9516         rsurface.passcolor4f_bufferoffset = 0;
9517
9518         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9519         {
9520                 f = 1 - RSurf_FogVertex(v);
9521                 c[0] = r;
9522                 c[1] = g;
9523                 c[2] = b;
9524                 c[3] = f * a;
9525         }
9526 }
9527
9528 void RSurf_SetupDepthAndCulling(void)
9529 {
9530         // submodels are biased to avoid z-fighting with world surfaces that they
9531         // may be exactly overlapping (avoids z-fighting artifacts on certain
9532         // doors and things in Quake maps)
9533         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9534         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9535         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9536         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9537 }
9538
9539 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9540 {
9541         // transparent sky would be ridiculous
9542         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9543                 return;
9544         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9545         skyrenderlater = true;
9546         RSurf_SetupDepthAndCulling();
9547         GL_DepthMask(true);
9548         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9549         // skymasking on them, and Quake3 never did sky masking (unlike
9550         // software Quake and software Quake2), so disable the sky masking
9551         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9552         // and skymasking also looks very bad when noclipping outside the
9553         // level, so don't use it then either.
9554         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9555         {
9556                 R_Mesh_ResetTextureState();
9557                 if (skyrendermasked)
9558                 {
9559                         R_SetupShader_DepthOrShadow(false);
9560                         // depth-only (masking)
9561                         GL_ColorMask(0,0,0,0);
9562                         // just to make sure that braindead drivers don't draw
9563                         // anything despite that colormask...
9564                         GL_BlendFunc(GL_ZERO, GL_ONE);
9565                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9566                         if (rsurface.batchvertex3fbuffer)
9567                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9568                         else
9569                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9570                 }
9571                 else
9572                 {
9573                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9574                         // fog sky
9575                         GL_BlendFunc(GL_ONE, GL_ZERO);
9576                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9577                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9578                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9579                 }
9580                 RSurf_DrawBatch();
9581                 if (skyrendermasked)
9582                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9583         }
9584         R_Mesh_ResetTextureState();
9585         GL_Color(1, 1, 1, 1);
9586 }
9587
9588 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9589 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9590 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9591 {
9592         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9593                 return;
9594         if (prepass)
9595         {
9596                 // render screenspace normalmap to texture
9597                 GL_DepthMask(true);
9598                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9599                 RSurf_DrawBatch();
9600         }
9601
9602         // bind lightmap texture
9603
9604         // water/refraction/reflection/camera surfaces have to be handled specially
9605         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9606         {
9607                 int start, end, startplaneindex;
9608                 for (start = 0;start < texturenumsurfaces;start = end)
9609                 {
9610                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9611                         if(startplaneindex < 0)
9612                         {
9613                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9614                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9615                                 end = start + 1;
9616                                 continue;
9617                         }
9618                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9619                                 ;
9620                         // now that we have a batch using the same planeindex, render it
9621                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9622                         {
9623                                 // render water or distortion background
9624                                 GL_DepthMask(true);
9625                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9626                                 RSurf_DrawBatch();
9627                                 // blend surface on top
9628                                 GL_DepthMask(false);
9629                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9630                                 RSurf_DrawBatch();
9631                         }
9632                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9633                         {
9634                                 // render surface with reflection texture as input
9635                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9636                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9637                                 RSurf_DrawBatch();
9638                         }
9639                 }
9640                 return;
9641         }
9642
9643         // render surface batch normally
9644         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9645         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9646         RSurf_DrawBatch();
9647 }
9648
9649 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9650 {
9651         // OpenGL 1.3 path - anything not completely ancient
9652         qboolean applycolor;
9653         qboolean applyfog;
9654         int layerindex;
9655         const texturelayer_t *layer;
9656         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);
9657         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9658
9659         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9660         {
9661                 vec4_t layercolor;
9662                 int layertexrgbscale;
9663                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9664                 {
9665                         if (layerindex == 0)
9666                                 GL_AlphaTest(true);
9667                         else
9668                         {
9669                                 GL_AlphaTest(false);
9670                                 GL_DepthFunc(GL_EQUAL);
9671                         }
9672                 }
9673                 GL_DepthMask(layer->depthmask && writedepth);
9674                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9675                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9676                 {
9677                         layertexrgbscale = 4;
9678                         VectorScale(layer->color, 0.25f, layercolor);
9679                 }
9680                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9681                 {
9682                         layertexrgbscale = 2;
9683                         VectorScale(layer->color, 0.5f, layercolor);
9684                 }
9685                 else
9686                 {
9687                         layertexrgbscale = 1;
9688                         VectorScale(layer->color, 1.0f, layercolor);
9689                 }
9690                 layercolor[3] = layer->color[3];
9691                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9692                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9693                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9694                 switch (layer->type)
9695                 {
9696                 case TEXTURELAYERTYPE_LITTEXTURE:
9697                         // single-pass lightmapped texture with 2x rgbscale
9698                         R_Mesh_TexBind(0, r_texture_white);
9699                         R_Mesh_TexMatrix(0, NULL);
9700                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9701                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9702                         R_Mesh_TexBind(1, layer->texture);
9703                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9704                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9705                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9706                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9707                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9708                         else if (FAKELIGHT_ENABLED)
9709                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9710                         else if (rsurface.uselightmaptexture)
9711                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9712                         else
9713                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9714                         break;
9715                 case TEXTURELAYERTYPE_TEXTURE:
9716                         // singletexture unlit texture with transparency support
9717                         R_Mesh_TexBind(0, layer->texture);
9718                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9719                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9720                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9721                         R_Mesh_TexBind(1, 0);
9722                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9723                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9724                         break;
9725                 case TEXTURELAYERTYPE_FOG:
9726                         // singletexture fogging
9727                         if (layer->texture)
9728                         {
9729                                 R_Mesh_TexBind(0, layer->texture);
9730                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9731                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9732                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9733                         }
9734                         else
9735                         {
9736                                 R_Mesh_TexBind(0, 0);
9737                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9738                         }
9739                         R_Mesh_TexBind(1, 0);
9740                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9741                         // generate a color array for the fog pass
9742                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9743                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9744                         RSurf_DrawBatch();
9745                         break;
9746                 default:
9747                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9748                 }
9749         }
9750         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9751         {
9752                 GL_DepthFunc(GL_LEQUAL);
9753                 GL_AlphaTest(false);
9754         }
9755 }
9756
9757 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9758 {
9759         // OpenGL 1.1 - crusty old voodoo path
9760         qboolean applyfog;
9761         int layerindex;
9762         const texturelayer_t *layer;
9763         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);
9764         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9765
9766         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9767         {
9768                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9769                 {
9770                         if (layerindex == 0)
9771                                 GL_AlphaTest(true);
9772                         else
9773                         {
9774                                 GL_AlphaTest(false);
9775                                 GL_DepthFunc(GL_EQUAL);
9776                         }
9777                 }
9778                 GL_DepthMask(layer->depthmask && writedepth);
9779                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9780                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9781                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9782                 switch (layer->type)
9783                 {
9784                 case TEXTURELAYERTYPE_LITTEXTURE:
9785                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9786                         {
9787                                 // two-pass lit texture with 2x rgbscale
9788                                 // first the lightmap pass
9789                                 R_Mesh_TexBind(0, r_texture_white);
9790                                 R_Mesh_TexMatrix(0, NULL);
9791                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9792                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9793                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9795                                 else if (FAKELIGHT_ENABLED)
9796                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9797                                 else if (rsurface.uselightmaptexture)
9798                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9799                                 else
9800                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9801                                 // then apply the texture to it
9802                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9803                                 R_Mesh_TexBind(0, layer->texture);
9804                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9805                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9806                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9807                                 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);
9808                         }
9809                         else
9810                         {
9811                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9812                                 R_Mesh_TexBind(0, layer->texture);
9813                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9814                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9815                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9816                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9817                                         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);
9818                                 else
9819                                         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);
9820                         }
9821                         break;
9822                 case TEXTURELAYERTYPE_TEXTURE:
9823                         // singletexture unlit texture with transparency support
9824                         R_Mesh_TexBind(0, layer->texture);
9825                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9826                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9827                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9828                         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);
9829                         break;
9830                 case TEXTURELAYERTYPE_FOG:
9831                         // singletexture fogging
9832                         if (layer->texture)
9833                         {
9834                                 R_Mesh_TexBind(0, layer->texture);
9835                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9836                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9837                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9838                         }
9839                         else
9840                         {
9841                                 R_Mesh_TexBind(0, 0);
9842                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9843                         }
9844                         // generate a color array for the fog pass
9845                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9846                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9847                         RSurf_DrawBatch();
9848                         break;
9849                 default:
9850                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9851                 }
9852         }
9853         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9854         {
9855                 GL_DepthFunc(GL_LEQUAL);
9856                 GL_AlphaTest(false);
9857         }
9858 }
9859
9860 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9861 {
9862         int vi;
9863         int j;
9864         r_vertexgeneric_t *batchvertex;
9865         float c[4];
9866
9867 //      R_Mesh_ResetTextureState();
9868         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9869
9870         if(rsurface.texture && rsurface.texture->currentskinframe)
9871         {
9872                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9873                 c[3] *= rsurface.texture->currentalpha;
9874         }
9875         else
9876         {
9877                 c[0] = 1;
9878                 c[1] = 0;
9879                 c[2] = 1;
9880                 c[3] = 1;
9881         }
9882
9883         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9884         {
9885                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9886                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9887                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9888         }
9889
9890         // brighten it up (as texture value 127 means "unlit")
9891         c[0] *= 2 * r_refdef.view.colorscale;
9892         c[1] *= 2 * r_refdef.view.colorscale;
9893         c[2] *= 2 * r_refdef.view.colorscale;
9894
9895         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9896                 c[3] *= r_wateralpha.value;
9897
9898         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9899         {
9900                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9901                 GL_DepthMask(false);
9902         }
9903         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9904         {
9905                 GL_BlendFunc(GL_ONE, GL_ONE);
9906                 GL_DepthMask(false);
9907         }
9908         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9909         {
9910                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9911                 GL_DepthMask(false);
9912         }
9913         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9914         {
9915                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9916                 GL_DepthMask(false);
9917         }
9918         else
9919         {
9920                 GL_BlendFunc(GL_ONE, GL_ZERO);
9921                 GL_DepthMask(writedepth);
9922         }
9923
9924         if (r_showsurfaces.integer == 3)
9925         {
9926                 rsurface.passcolor4f = NULL;
9927
9928                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9929                 {
9930                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9931
9932                         rsurface.passcolor4f = NULL;
9933                         rsurface.passcolor4f_vertexbuffer = 0;
9934                         rsurface.passcolor4f_bufferoffset = 0;
9935                 }
9936                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9937                 {
9938                         qboolean applycolor = true;
9939                         float one = 1.0;
9940
9941                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9942
9943                         r_refdef.lightmapintensity = 1;
9944                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9945                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9946                 }
9947                 else if (FAKELIGHT_ENABLED)
9948                 {
9949                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9950
9951                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9952                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9953                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9954                 }
9955                 else
9956                 {
9957                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9958
9959                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9960                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9961                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9962                 }
9963
9964                 if(!rsurface.passcolor4f)
9965                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9966
9967                 RSurf_DrawBatch_GL11_ApplyAmbient();
9968                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9969                 if(r_refdef.fogenabled)
9970                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9971                 RSurf_DrawBatch_GL11_ClampColor();
9972
9973                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9974                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9975                 RSurf_DrawBatch();
9976         }
9977         else if (!r_refdef.view.showdebug)
9978         {
9979                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9980                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9981                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9982                 {
9983                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9984                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9985                 }
9986                 R_Mesh_PrepareVertices_Generic_Unlock();
9987                 RSurf_DrawBatch();
9988         }
9989         else if (r_showsurfaces.integer == 4)
9990         {
9991                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9992                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9993                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9994                 {
9995                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9996                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9997                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9998                 }
9999                 R_Mesh_PrepareVertices_Generic_Unlock();
10000                 RSurf_DrawBatch();
10001         }
10002         else if (r_showsurfaces.integer == 2)
10003         {
10004                 const int *e;
10005                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10006                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10007                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10008                 {
10009                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10010                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10011                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10012                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10013                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10014                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10015                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10016                 }
10017                 R_Mesh_PrepareVertices_Generic_Unlock();
10018                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10019         }
10020         else
10021         {
10022                 int texturesurfaceindex;
10023                 int k;
10024                 const msurface_t *surface;
10025                 float surfacecolor4f[4];
10026                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10027                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10028                 vi = 0;
10029                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10030                 {
10031                         surface = texturesurfacelist[texturesurfaceindex];
10032                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10033                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10034                         for (j = 0;j < surface->num_vertices;j++)
10035                         {
10036                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10037                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10038                                 vi++;
10039                         }
10040                 }
10041                 R_Mesh_PrepareVertices_Generic_Unlock();
10042                 RSurf_DrawBatch();
10043         }
10044 }
10045
10046 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10047 {
10048         CHECKGLERROR
10049         RSurf_SetupDepthAndCulling();
10050         if (r_showsurfaces.integer)
10051         {
10052                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10053                 return;
10054         }
10055         switch (vid.renderpath)
10056         {
10057         case RENDERPATH_GL20:
10058         case RENDERPATH_D3D9:
10059         case RENDERPATH_D3D10:
10060         case RENDERPATH_D3D11:
10061         case RENDERPATH_SOFT:
10062         case RENDERPATH_GLES2:
10063                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10064                 break;
10065         case RENDERPATH_GL13:
10066         case RENDERPATH_GLES1:
10067                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10068                 break;
10069         case RENDERPATH_GL11:
10070                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10071                 break;
10072         }
10073         CHECKGLERROR
10074 }
10075
10076 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10077 {
10078         CHECKGLERROR
10079         RSurf_SetupDepthAndCulling();
10080         if (r_showsurfaces.integer)
10081         {
10082                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10083                 return;
10084         }
10085         switch (vid.renderpath)
10086         {
10087         case RENDERPATH_GL20:
10088         case RENDERPATH_D3D9:
10089         case RENDERPATH_D3D10:
10090         case RENDERPATH_D3D11:
10091         case RENDERPATH_SOFT:
10092         case RENDERPATH_GLES2:
10093                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10094                 break;
10095         case RENDERPATH_GL13:
10096         case RENDERPATH_GLES1:
10097                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10098                 break;
10099         case RENDERPATH_GL11:
10100                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10101                 break;
10102         }
10103         CHECKGLERROR
10104 }
10105
10106 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10107 {
10108         int i, j;
10109         int texturenumsurfaces, endsurface;
10110         texture_t *texture;
10111         const msurface_t *surface;
10112         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10113
10114         // if the model is static it doesn't matter what value we give for
10115         // wantnormals and wanttangents, so this logic uses only rules applicable
10116         // to a model, knowing that they are meaningless otherwise
10117         if (ent == r_refdef.scene.worldentity)
10118                 RSurf_ActiveWorldEntity();
10119         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10120                 RSurf_ActiveModelEntity(ent, false, false, false);
10121         else
10122         {
10123                 switch (vid.renderpath)
10124                 {
10125                 case RENDERPATH_GL20:
10126                 case RENDERPATH_D3D9:
10127                 case RENDERPATH_D3D10:
10128                 case RENDERPATH_D3D11:
10129                 case RENDERPATH_SOFT:
10130                 case RENDERPATH_GLES2:
10131                         RSurf_ActiveModelEntity(ent, true, true, false);
10132                         break;
10133                 case RENDERPATH_GL11:
10134                 case RENDERPATH_GL13:
10135                 case RENDERPATH_GLES1:
10136                         RSurf_ActiveModelEntity(ent, true, false, false);
10137                         break;
10138                 }
10139         }
10140
10141         if (r_transparentdepthmasking.integer)
10142         {
10143                 qboolean setup = false;
10144                 for (i = 0;i < numsurfaces;i = j)
10145                 {
10146                         j = i + 1;
10147                         surface = rsurface.modelsurfaces + surfacelist[i];
10148                         texture = surface->texture;
10149                         rsurface.texture = R_GetCurrentTexture(texture);
10150                         rsurface.lightmaptexture = NULL;
10151                         rsurface.deluxemaptexture = NULL;
10152                         rsurface.uselightmaptexture = false;
10153                         // scan ahead until we find a different texture
10154                         endsurface = min(i + 1024, numsurfaces);
10155                         texturenumsurfaces = 0;
10156                         texturesurfacelist[texturenumsurfaces++] = surface;
10157                         for (;j < endsurface;j++)
10158                         {
10159                                 surface = rsurface.modelsurfaces + surfacelist[j];
10160                                 if (texture != surface->texture)
10161                                         break;
10162                                 texturesurfacelist[texturenumsurfaces++] = surface;
10163                         }
10164                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10165                                 continue;
10166                         // render the range of surfaces as depth
10167                         if (!setup)
10168                         {
10169                                 setup = true;
10170                                 GL_ColorMask(0,0,0,0);
10171                                 GL_Color(1,1,1,1);
10172                                 GL_DepthTest(true);
10173                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10174                                 GL_DepthMask(true);
10175 //                              R_Mesh_ResetTextureState();
10176                                 R_SetupShader_DepthOrShadow(false);
10177                         }
10178                         RSurf_SetupDepthAndCulling();
10179                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10180                         if (rsurface.batchvertex3fbuffer)
10181                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10182                         else
10183                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10184                         RSurf_DrawBatch();
10185                 }
10186                 if (setup)
10187                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10188         }
10189
10190         for (i = 0;i < numsurfaces;i = j)
10191         {
10192                 j = i + 1;
10193                 surface = rsurface.modelsurfaces + surfacelist[i];
10194                 texture = surface->texture;
10195                 rsurface.texture = R_GetCurrentTexture(texture);
10196                 // scan ahead until we find a different texture
10197                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10198                 texturenumsurfaces = 0;
10199                 texturesurfacelist[texturenumsurfaces++] = surface;
10200                 if(FAKELIGHT_ENABLED)
10201                 {
10202                         rsurface.lightmaptexture = NULL;
10203                         rsurface.deluxemaptexture = NULL;
10204                         rsurface.uselightmaptexture = false;
10205                         for (;j < endsurface;j++)
10206                         {
10207                                 surface = rsurface.modelsurfaces + surfacelist[j];
10208                                 if (texture != surface->texture)
10209                                         break;
10210                                 texturesurfacelist[texturenumsurfaces++] = surface;
10211                         }
10212                 }
10213                 else
10214                 {
10215                         rsurface.lightmaptexture = surface->lightmaptexture;
10216                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10217                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10218                         for (;j < endsurface;j++)
10219                         {
10220                                 surface = rsurface.modelsurfaces + surfacelist[j];
10221                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10222                                         break;
10223                                 texturesurfacelist[texturenumsurfaces++] = surface;
10224                         }
10225                 }
10226                 // render the range of surfaces
10227                 if (ent == r_refdef.scene.worldentity)
10228                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10229                 else
10230                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10231         }
10232         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10233 }
10234
10235 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10236 {
10237         // transparent surfaces get pushed off into the transparent queue
10238         int surfacelistindex;
10239         const msurface_t *surface;
10240         vec3_t tempcenter, center;
10241         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10242         {
10243                 surface = texturesurfacelist[surfacelistindex];
10244                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10245                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10246                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10247                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10248                 if (queueentity->transparent_offset) // transparent offset
10249                 {
10250                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10251                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10252                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10253                 }
10254                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10255         }
10256 }
10257
10258 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10259 {
10260         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10261                 return;
10262         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10263                 return;
10264         RSurf_SetupDepthAndCulling();
10265         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10266         if (rsurface.batchvertex3fbuffer)
10267                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10268         else
10269                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10270         RSurf_DrawBatch();
10271 }
10272
10273 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10274 {
10275         const entity_render_t *queueentity = r_refdef.scene.worldentity;
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_DrawWorldTextureSurfaceList(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_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10302         }
10303         CHECKGLERROR
10304 }
10305
10306 void R_QueueWorldSurfaceList(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_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10348         }
10349         R_FrameData_ReturnToMark();
10350 }
10351
10352 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10353 {
10354         CHECKGLERROR
10355         if (depthonly)
10356                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10357         else if (prepass)
10358         {
10359                 if (!rsurface.texture->currentnumlayers)
10360                         return;
10361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10362                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10363                 else
10364                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10365         }
10366         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10367                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10368         else if (!rsurface.texture->currentnumlayers)
10369                 return;
10370         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10371         {
10372                 // in the deferred case, transparent surfaces were queued during prepass
10373                 if (!r_shadow_usingdeferredprepass)
10374                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10375         }
10376         else
10377         {
10378                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10379                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10380         }
10381         CHECKGLERROR
10382 }
10383
10384 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10385 {
10386         int i, j;
10387         texture_t *texture;
10388         R_FrameData_SetMark();
10389         // break the surface list down into batches by texture and use of lightmapping
10390         for (i = 0;i < numsurfaces;i = j)
10391         {
10392                 j = i + 1;
10393                 // texture is the base texture pointer, rsurface.texture is the
10394                 // current frame/skin the texture is directing us to use (for example
10395                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10396                 // use skin 1 instead)
10397                 texture = surfacelist[i]->texture;
10398                 rsurface.texture = R_GetCurrentTexture(texture);
10399                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10400                 {
10401                         // if this texture is not the kind we want, skip ahead to the next one
10402                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10403                                 ;
10404                         continue;
10405                 }
10406                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10407                 {
10408                         rsurface.lightmaptexture = NULL;
10409                         rsurface.deluxemaptexture = NULL;
10410                         rsurface.uselightmaptexture = false;
10411                         // simply scan ahead until we find a different texture or lightmap state
10412                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10413                                 ;
10414                 }
10415                 else
10416                 {
10417                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10418                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10419                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10420                         // simply scan ahead until we find a different texture or lightmap state
10421                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10422                                 ;
10423                 }
10424                 // render the range of surfaces
10425                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10426         }
10427         R_FrameData_ReturnToMark();
10428 }
10429
10430 float locboxvertex3f[6*4*3] =
10431 {
10432         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10433         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10434         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10435         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10436         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10437         1,0,0, 0,0,0, 0,1,0, 1,1,0
10438 };
10439
10440 unsigned short locboxelements[6*2*3] =
10441 {
10442          0, 1, 2, 0, 2, 3,
10443          4, 5, 6, 4, 6, 7,
10444          8, 9,10, 8,10,11,
10445         12,13,14, 12,14,15,
10446         16,17,18, 16,18,19,
10447         20,21,22, 20,22,23
10448 };
10449
10450 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10451 {
10452         int i, j;
10453         cl_locnode_t *loc = (cl_locnode_t *)ent;
10454         vec3_t mins, size;
10455         float vertex3f[6*4*3];
10456         CHECKGLERROR
10457         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10458         GL_DepthMask(false);
10459         GL_DepthRange(0, 1);
10460         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10461         GL_DepthTest(true);
10462         GL_CullFace(GL_NONE);
10463         R_EntityMatrix(&identitymatrix);
10464
10465 //      R_Mesh_ResetTextureState();
10466
10467         i = surfacelist[0];
10468         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10469                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10470                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10471                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10472
10473         if (VectorCompare(loc->mins, loc->maxs))
10474         {
10475                 VectorSet(size, 2, 2, 2);
10476                 VectorMA(loc->mins, -0.5f, size, mins);
10477         }
10478         else
10479         {
10480                 VectorCopy(loc->mins, mins);
10481                 VectorSubtract(loc->maxs, loc->mins, size);
10482         }
10483
10484         for (i = 0;i < 6*4*3;)
10485                 for (j = 0;j < 3;j++, i++)
10486                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10487
10488         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10489         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10490         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10491 }
10492
10493 void R_DrawLocs(void)
10494 {
10495         int index;
10496         cl_locnode_t *loc, *nearestloc;
10497         vec3_t center;
10498         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10499         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10500         {
10501                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10502                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10503         }
10504 }
10505
10506 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10507 {
10508         if (decalsystem->decals)
10509                 Mem_Free(decalsystem->decals);
10510         memset(decalsystem, 0, sizeof(*decalsystem));
10511 }
10512
10513 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)
10514 {
10515         tridecal_t *decal;
10516         tridecal_t *decals;
10517         int i;
10518
10519         // expand or initialize the system
10520         if (decalsystem->maxdecals <= decalsystem->numdecals)
10521         {
10522                 decalsystem_t old = *decalsystem;
10523                 qboolean useshortelements;
10524                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10525                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10526                 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)));
10527                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10528                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10529                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10530                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10531                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10532                 if (decalsystem->numdecals)
10533                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10534                 if (old.decals)
10535                         Mem_Free(old.decals);
10536                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10537                         decalsystem->element3i[i] = i;
10538                 if (useshortelements)
10539                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10540                                 decalsystem->element3s[i] = i;
10541         }
10542
10543         // grab a decal and search for another free slot for the next one
10544         decals = decalsystem->decals;
10545         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10546         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10547                 ;
10548         decalsystem->freedecal = i;
10549         if (decalsystem->numdecals <= i)
10550                 decalsystem->numdecals = i + 1;
10551
10552         // initialize the decal
10553         decal->lived = 0;
10554         decal->triangleindex = triangleindex;
10555         decal->surfaceindex = surfaceindex;
10556         decal->decalsequence = decalsequence;
10557         decal->color4f[0][0] = c0[0];
10558         decal->color4f[0][1] = c0[1];
10559         decal->color4f[0][2] = c0[2];
10560         decal->color4f[0][3] = 1;
10561         decal->color4f[1][0] = c1[0];
10562         decal->color4f[1][1] = c1[1];
10563         decal->color4f[1][2] = c1[2];
10564         decal->color4f[1][3] = 1;
10565         decal->color4f[2][0] = c2[0];
10566         decal->color4f[2][1] = c2[1];
10567         decal->color4f[2][2] = c2[2];
10568         decal->color4f[2][3] = 1;
10569         decal->vertex3f[0][0] = v0[0];
10570         decal->vertex3f[0][1] = v0[1];
10571         decal->vertex3f[0][2] = v0[2];
10572         decal->vertex3f[1][0] = v1[0];
10573         decal->vertex3f[1][1] = v1[1];
10574         decal->vertex3f[1][2] = v1[2];
10575         decal->vertex3f[2][0] = v2[0];
10576         decal->vertex3f[2][1] = v2[1];
10577         decal->vertex3f[2][2] = v2[2];
10578         decal->texcoord2f[0][0] = t0[0];
10579         decal->texcoord2f[0][1] = t0[1];
10580         decal->texcoord2f[1][0] = t1[0];
10581         decal->texcoord2f[1][1] = t1[1];
10582         decal->texcoord2f[2][0] = t2[0];
10583         decal->texcoord2f[2][1] = t2[1];
10584         TriangleNormal(v0, v1, v2, decal->plane);
10585         VectorNormalize(decal->plane);
10586         decal->plane[3] = DotProduct(v0, decal->plane);
10587 }
10588
10589 extern cvar_t cl_decals_bias;
10590 extern cvar_t cl_decals_models;
10591 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10592 // baseparms, parms, temps
10593 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)
10594 {
10595         int cornerindex;
10596         int index;
10597         float v[9][3];
10598         const float *vertex3f;
10599         const float *normal3f;
10600         int numpoints;
10601         float points[2][9][3];
10602         float temp[3];
10603         float tc[9][2];
10604         float f;
10605         float c[9][4];
10606         const int *e;
10607
10608         e = rsurface.modelelement3i + 3*triangleindex;
10609
10610         vertex3f = rsurface.modelvertex3f;
10611         normal3f = rsurface.modelnormal3f;
10612
10613         if (normal3f)
10614         {
10615                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10616                 {
10617                         index = 3*e[cornerindex];
10618                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10619                 }
10620         }
10621         else
10622         {
10623                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10624                 {
10625                         index = 3*e[cornerindex];
10626                         VectorCopy(vertex3f + index, v[cornerindex]);
10627                 }
10628         }
10629
10630         // cull backfaces
10631         //TriangleNormal(v[0], v[1], v[2], normal);
10632         //if (DotProduct(normal, localnormal) < 0.0f)
10633         //      continue;
10634         // clip by each of the box planes formed from the projection matrix
10635         // if anything survives, we emit the decal
10636         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]);
10637         if (numpoints < 3)
10638                 return;
10639         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]);
10640         if (numpoints < 3)
10641                 return;
10642         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]);
10643         if (numpoints < 3)
10644                 return;
10645         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]);
10646         if (numpoints < 3)
10647                 return;
10648         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]);
10649         if (numpoints < 3)
10650                 return;
10651         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]);
10652         if (numpoints < 3)
10653                 return;
10654         // some part of the triangle survived, so we have to accept it...
10655         if (dynamic)
10656         {
10657                 // dynamic always uses the original triangle
10658                 numpoints = 3;
10659                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10660                 {
10661                         index = 3*e[cornerindex];
10662                         VectorCopy(vertex3f + index, v[cornerindex]);
10663                 }
10664         }
10665         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10666         {
10667                 // convert vertex positions to texcoords
10668                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10669                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10670                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10671                 // calculate distance fade from the projection origin
10672                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10673                 f = bound(0.0f, f, 1.0f);
10674                 c[cornerindex][0] = r * f;
10675                 c[cornerindex][1] = g * f;
10676                 c[cornerindex][2] = b * f;
10677                 c[cornerindex][3] = 1.0f;
10678                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10679         }
10680         if (dynamic)
10681                 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);
10682         else
10683                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10684                         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);
10685 }
10686 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)
10687 {
10688         matrix4x4_t projection;
10689         decalsystem_t *decalsystem;
10690         qboolean dynamic;
10691         dp_model_t *model;
10692         const msurface_t *surface;
10693         const msurface_t *surfaces;
10694         const int *surfacelist;
10695         const texture_t *texture;
10696         int numtriangles;
10697         int numsurfacelist;
10698         int surfacelistindex;
10699         int surfaceindex;
10700         int triangleindex;
10701         float localorigin[3];
10702         float localnormal[3];
10703         float localmins[3];
10704         float localmaxs[3];
10705         float localsize;
10706         //float normal[3];
10707         float planes[6][4];
10708         float angles[3];
10709         bih_t *bih;
10710         int bih_triangles_count;
10711         int bih_triangles[256];
10712         int bih_surfaces[256];
10713
10714         decalsystem = &ent->decalsystem;
10715         model = ent->model;
10716         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10717         {
10718                 R_DecalSystem_Reset(&ent->decalsystem);
10719                 return;
10720         }
10721
10722         if (!model->brush.data_leafs && !cl_decals_models.integer)
10723         {
10724                 if (decalsystem->model)
10725                         R_DecalSystem_Reset(decalsystem);
10726                 return;
10727         }
10728
10729         if (decalsystem->model != model)
10730                 R_DecalSystem_Reset(decalsystem);
10731         decalsystem->model = model;
10732
10733         RSurf_ActiveModelEntity(ent, true, false, false);
10734
10735         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10736         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10737         VectorNormalize(localnormal);
10738         localsize = worldsize*rsurface.inversematrixscale;
10739         localmins[0] = localorigin[0] - localsize;
10740         localmins[1] = localorigin[1] - localsize;
10741         localmins[2] = localorigin[2] - localsize;
10742         localmaxs[0] = localorigin[0] + localsize;
10743         localmaxs[1] = localorigin[1] + localsize;
10744         localmaxs[2] = localorigin[2] + localsize;
10745
10746         //VectorCopy(localnormal, planes[4]);
10747         //VectorVectors(planes[4], planes[2], planes[0]);
10748         AnglesFromVectors(angles, localnormal, NULL, false);
10749         AngleVectors(angles, planes[0], planes[2], planes[4]);
10750         VectorNegate(planes[0], planes[1]);
10751         VectorNegate(planes[2], planes[3]);
10752         VectorNegate(planes[4], planes[5]);
10753         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10754         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10755         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10756         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10757         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10758         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10759
10760 #if 1
10761 // works
10762 {
10763         matrix4x4_t forwardprojection;
10764         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10765         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10766 }
10767 #else
10768 // broken
10769 {
10770         float projectionvector[4][3];
10771         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10772         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10773         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10774         projectionvector[0][0] = planes[0][0] * ilocalsize;
10775         projectionvector[0][1] = planes[1][0] * ilocalsize;
10776         projectionvector[0][2] = planes[2][0] * ilocalsize;
10777         projectionvector[1][0] = planes[0][1] * ilocalsize;
10778         projectionvector[1][1] = planes[1][1] * ilocalsize;
10779         projectionvector[1][2] = planes[2][1] * ilocalsize;
10780         projectionvector[2][0] = planes[0][2] * ilocalsize;
10781         projectionvector[2][1] = planes[1][2] * ilocalsize;
10782         projectionvector[2][2] = planes[2][2] * ilocalsize;
10783         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10784         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10785         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10786         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10787 }
10788 #endif
10789
10790         dynamic = model->surfmesh.isanimated;
10791         numsurfacelist = model->nummodelsurfaces;
10792         surfacelist = model->sortedmodelsurfaces;
10793         surfaces = model->data_surfaces;
10794
10795         bih = NULL;
10796         bih_triangles_count = -1;
10797         if(!dynamic)
10798         {
10799                 if(model->render_bih.numleafs)
10800                         bih = &model->render_bih;
10801                 else if(model->collision_bih.numleafs)
10802                         bih = &model->collision_bih;
10803         }
10804         if(bih)
10805                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10806         if(bih_triangles_count == 0)
10807                 return;
10808         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10809                 return;
10810         if(bih_triangles_count > 0)
10811         {
10812                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10813                 {
10814                         surfaceindex = bih_surfaces[triangleindex];
10815                         surface = surfaces + surfaceindex;
10816                         texture = surface->texture;
10817                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10818                                 continue;
10819                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10820                                 continue;
10821                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10822                 }
10823         }
10824         else
10825         {
10826                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10827                 {
10828                         surfaceindex = surfacelist[surfacelistindex];
10829                         surface = surfaces + surfaceindex;
10830                         // check cull box first because it rejects more than any other check
10831                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10832                                 continue;
10833                         // skip transparent surfaces
10834                         texture = surface->texture;
10835                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10836                                 continue;
10837                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10838                                 continue;
10839                         numtriangles = surface->num_triangles;
10840                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10841                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10842                 }
10843         }
10844 }
10845
10846 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10847 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)
10848 {
10849         int renderentityindex;
10850         float worldmins[3];
10851         float worldmaxs[3];
10852         entity_render_t *ent;
10853
10854         if (!cl_decals_newsystem.integer)
10855                 return;
10856
10857         worldmins[0] = worldorigin[0] - worldsize;
10858         worldmins[1] = worldorigin[1] - worldsize;
10859         worldmins[2] = worldorigin[2] - worldsize;
10860         worldmaxs[0] = worldorigin[0] + worldsize;
10861         worldmaxs[1] = worldorigin[1] + worldsize;
10862         worldmaxs[2] = worldorigin[2] + worldsize;
10863
10864         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10865
10866         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10867         {
10868                 ent = r_refdef.scene.entities[renderentityindex];
10869                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10870                         continue;
10871
10872                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10873         }
10874 }
10875
10876 typedef struct r_decalsystem_splatqueue_s
10877 {
10878         vec3_t worldorigin;
10879         vec3_t worldnormal;
10880         float color[4];
10881         float tcrange[4];
10882         float worldsize;
10883         int decalsequence;
10884 }
10885 r_decalsystem_splatqueue_t;
10886
10887 int r_decalsystem_numqueued = 0;
10888 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10889
10890 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)
10891 {
10892         r_decalsystem_splatqueue_t *queue;
10893
10894         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10895                 return;
10896
10897         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10898         VectorCopy(worldorigin, queue->worldorigin);
10899         VectorCopy(worldnormal, queue->worldnormal);
10900         Vector4Set(queue->color, r, g, b, a);
10901         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10902         queue->worldsize = worldsize;
10903         queue->decalsequence = cl.decalsequence++;
10904 }
10905
10906 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10907 {
10908         int i;
10909         r_decalsystem_splatqueue_t *queue;
10910
10911         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10912                 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);
10913         r_decalsystem_numqueued = 0;
10914 }
10915
10916 extern cvar_t cl_decals_max;
10917 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10918 {
10919         int i;
10920         decalsystem_t *decalsystem = &ent->decalsystem;
10921         int numdecals;
10922         int killsequence;
10923         tridecal_t *decal;
10924         float frametime;
10925         float lifetime;
10926
10927         if (!decalsystem->numdecals)
10928                 return;
10929
10930         if (r_showsurfaces.integer)
10931                 return;
10932
10933         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10934         {
10935                 R_DecalSystem_Reset(decalsystem);
10936                 return;
10937         }
10938
10939         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10940         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10941
10942         if (decalsystem->lastupdatetime)
10943                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10944         else
10945                 frametime = 0;
10946         decalsystem->lastupdatetime = r_refdef.scene.time;
10947         decal = decalsystem->decals;
10948         numdecals = decalsystem->numdecals;
10949
10950         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10951         {
10952                 if (decal->color4f[0][3])
10953                 {
10954                         decal->lived += frametime;
10955                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10956                         {
10957                                 memset(decal, 0, sizeof(*decal));
10958                                 if (decalsystem->freedecal > i)
10959                                         decalsystem->freedecal = i;
10960                         }
10961                 }
10962         }
10963         decal = decalsystem->decals;
10964         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10965                 numdecals--;
10966
10967         // collapse the array by shuffling the tail decals into the gaps
10968         for (;;)
10969         {
10970                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10971                         decalsystem->freedecal++;
10972                 if (decalsystem->freedecal == numdecals)
10973                         break;
10974                 decal[decalsystem->freedecal] = decal[--numdecals];
10975         }
10976
10977         decalsystem->numdecals = numdecals;
10978
10979         if (numdecals <= 0)
10980         {
10981                 // if there are no decals left, reset decalsystem
10982                 R_DecalSystem_Reset(decalsystem);
10983         }
10984 }
10985
10986 extern skinframe_t *decalskinframe;
10987 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10988 {
10989         int i;
10990         decalsystem_t *decalsystem = &ent->decalsystem;
10991         int numdecals;
10992         tridecal_t *decal;
10993         float faderate;
10994         float alpha;
10995         float *v3f;
10996         float *c4f;
10997         float *t2f;
10998         const int *e;
10999         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11000         int numtris = 0;
11001
11002         numdecals = decalsystem->numdecals;
11003         if (!numdecals)
11004                 return;
11005
11006         if (r_showsurfaces.integer)
11007                 return;
11008
11009         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11010         {
11011                 R_DecalSystem_Reset(decalsystem);
11012                 return;
11013         }
11014
11015         // if the model is static it doesn't matter what value we give for
11016         // wantnormals and wanttangents, so this logic uses only rules applicable
11017         // to a model, knowing that they are meaningless otherwise
11018         if (ent == r_refdef.scene.worldentity)
11019                 RSurf_ActiveWorldEntity();
11020         else
11021                 RSurf_ActiveModelEntity(ent, false, false, false);
11022
11023         decalsystem->lastupdatetime = r_refdef.scene.time;
11024         decal = decalsystem->decals;
11025
11026         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11027
11028         // update vertex positions for animated models
11029         v3f = decalsystem->vertex3f;
11030         c4f = decalsystem->color4f;
11031         t2f = decalsystem->texcoord2f;
11032         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11033         {
11034                 if (!decal->color4f[0][3])
11035                         continue;
11036
11037                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11038                         continue;
11039
11040                 // skip backfaces
11041                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11042                         continue;
11043
11044                 // update color values for fading decals
11045                 if (decal->lived >= cl_decals_time.value)
11046                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11047                 else
11048                         alpha = 1.0f;
11049
11050                 c4f[ 0] = decal->color4f[0][0] * alpha;
11051                 c4f[ 1] = decal->color4f[0][1] * alpha;
11052                 c4f[ 2] = decal->color4f[0][2] * alpha;
11053                 c4f[ 3] = 1;
11054                 c4f[ 4] = decal->color4f[1][0] * alpha;
11055                 c4f[ 5] = decal->color4f[1][1] * alpha;
11056                 c4f[ 6] = decal->color4f[1][2] * alpha;
11057                 c4f[ 7] = 1;
11058                 c4f[ 8] = decal->color4f[2][0] * alpha;
11059                 c4f[ 9] = decal->color4f[2][1] * alpha;
11060                 c4f[10] = decal->color4f[2][2] * alpha;
11061                 c4f[11] = 1;
11062
11063                 t2f[0] = decal->texcoord2f[0][0];
11064                 t2f[1] = decal->texcoord2f[0][1];
11065                 t2f[2] = decal->texcoord2f[1][0];
11066                 t2f[3] = decal->texcoord2f[1][1];
11067                 t2f[4] = decal->texcoord2f[2][0];
11068                 t2f[5] = decal->texcoord2f[2][1];
11069
11070                 // update vertex positions for animated models
11071                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11072                 {
11073                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11074                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11075                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11076                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11077                 }
11078                 else
11079                 {
11080                         VectorCopy(decal->vertex3f[0], v3f);
11081                         VectorCopy(decal->vertex3f[1], v3f + 3);
11082                         VectorCopy(decal->vertex3f[2], v3f + 6);
11083                 }
11084
11085                 if (r_refdef.fogenabled)
11086                 {
11087                         alpha = RSurf_FogVertex(v3f);
11088                         VectorScale(c4f, alpha, c4f);
11089                         alpha = RSurf_FogVertex(v3f + 3);
11090                         VectorScale(c4f + 4, alpha, c4f + 4);
11091                         alpha = RSurf_FogVertex(v3f + 6);
11092                         VectorScale(c4f + 8, alpha, c4f + 8);
11093                 }
11094
11095                 v3f += 9;
11096                 c4f += 12;
11097                 t2f += 6;
11098                 numtris++;
11099         }
11100
11101         if (numtris > 0)
11102         {
11103                 r_refdef.stats.drawndecals += numtris;
11104
11105                 // now render the decals all at once
11106                 // (this assumes they all use one particle font texture!)
11107                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11108 //              R_Mesh_ResetTextureState();
11109                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11110                 GL_DepthMask(false);
11111                 GL_DepthRange(0, 1);
11112                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11113                 GL_DepthTest(true);
11114                 GL_CullFace(GL_NONE);
11115                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11116                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11117                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11118         }
11119 }
11120
11121 static void R_DrawModelDecals(void)
11122 {
11123         int i, numdecals;
11124
11125         // fade faster when there are too many decals
11126         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11127         for (i = 0;i < r_refdef.scene.numentities;i++)
11128                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11129
11130         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11131         for (i = 0;i < r_refdef.scene.numentities;i++)
11132                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11133                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11134
11135         R_DecalSystem_ApplySplatEntitiesQueue();
11136
11137         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11138         for (i = 0;i < r_refdef.scene.numentities;i++)
11139                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11140
11141         r_refdef.stats.totaldecals += numdecals;
11142
11143         if (r_showsurfaces.integer)
11144                 return;
11145
11146         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11147
11148         for (i = 0;i < r_refdef.scene.numentities;i++)
11149         {
11150                 if (!r_refdef.viewcache.entityvisible[i])
11151                         continue;
11152                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11153                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11154         }
11155 }
11156
11157 extern cvar_t mod_collision_bih;
11158 void R_DrawDebugModel(void)
11159 {
11160         entity_render_t *ent = rsurface.entity;
11161         int i, j, k, l, flagsmask;
11162         const msurface_t *surface;
11163         dp_model_t *model = ent->model;
11164         vec3_t v;
11165
11166         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11167                 return;
11168
11169         if (r_showoverdraw.value > 0)
11170         {
11171                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11172                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11173                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11174                 GL_DepthTest(false);
11175                 GL_DepthMask(false);
11176                 GL_DepthRange(0, 1);
11177                 GL_BlendFunc(GL_ONE, GL_ONE);
11178                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11179                 {
11180                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11181                                 continue;
11182                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11183                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11184                         {
11185                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11186                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11187                                 if (!rsurface.texture->currentlayers->depthmask)
11188                                         GL_Color(c, 0, 0, 1.0f);
11189                                 else if (ent == r_refdef.scene.worldentity)
11190                                         GL_Color(c, c, c, 1.0f);
11191                                 else
11192                                         GL_Color(0, c, 0, 1.0f);
11193                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11194                                 RSurf_DrawBatch();
11195                         }
11196                 }
11197                 rsurface.texture = NULL;
11198         }
11199
11200         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11201
11202 //      R_Mesh_ResetTextureState();
11203         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11204         GL_DepthRange(0, 1);
11205         GL_DepthTest(!r_showdisabledepthtest.integer);
11206         GL_DepthMask(false);
11207         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11208
11209         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11210         {
11211                 int triangleindex;
11212                 int bihleafindex;
11213                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11214                 const q3mbrush_t *brush;
11215                 const bih_t *bih = &model->collision_bih;
11216                 const bih_leaf_t *bihleaf;
11217                 float vertex3f[3][3];
11218                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11219                 cullbox = false;
11220                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11221                 {
11222                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11223                                 continue;
11224                         switch (bihleaf->type)
11225                         {
11226                         case BIH_BRUSH:
11227                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11228                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11229                                 {
11230                                         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);
11231                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11232                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11233                                 }
11234                                 break;
11235                         case BIH_COLLISIONTRIANGLE:
11236                                 triangleindex = bihleaf->itemindex;
11237                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11238                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11239                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11240                                 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);
11241                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11242                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11243                                 break;
11244                         case BIH_RENDERTRIANGLE:
11245                                 triangleindex = bihleaf->itemindex;
11246                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11247                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11248                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11249                                 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);
11250                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11251                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11252                                 break;
11253                         }
11254                 }
11255         }
11256
11257         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11258
11259         if (r_showtris.integer && qglPolygonMode)
11260         {
11261                 if (r_showdisabledepthtest.integer)
11262                 {
11263                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11264                         GL_DepthMask(false);
11265                 }
11266                 else
11267                 {
11268                         GL_BlendFunc(GL_ONE, GL_ZERO);
11269                         GL_DepthMask(true);
11270                 }
11271                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11272                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11273                 {
11274                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11275                                 continue;
11276                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11277                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11278                         {
11279                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11280                                 if (!rsurface.texture->currentlayers->depthmask)
11281                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11282                                 else if (ent == r_refdef.scene.worldentity)
11283                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11284                                 else
11285                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11286                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11287                                 RSurf_DrawBatch();
11288                         }
11289                 }
11290                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11291                 rsurface.texture = NULL;
11292         }
11293
11294         if (r_shownormals.value != 0 && qglBegin)
11295         {
11296                 if (r_showdisabledepthtest.integer)
11297                 {
11298                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11299                         GL_DepthMask(false);
11300                 }
11301                 else
11302                 {
11303                         GL_BlendFunc(GL_ONE, GL_ZERO);
11304                         GL_DepthMask(true);
11305                 }
11306                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11307                 {
11308                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11309                                 continue;
11310                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11311                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11312                         {
11313                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11314                                 qglBegin(GL_LINES);
11315                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11316                                 {
11317                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11318                                         {
11319                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11320                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11321                                                 qglVertex3f(v[0], v[1], v[2]);
11322                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11323                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11324                                                 qglVertex3f(v[0], v[1], v[2]);
11325                                         }
11326                                 }
11327                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11328                                 {
11329                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11330                                         {
11331                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11332                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11333                                                 qglVertex3f(v[0], v[1], v[2]);
11334                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11335                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11336                                                 qglVertex3f(v[0], v[1], v[2]);
11337                                         }
11338                                 }
11339                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11340                                 {
11341                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11342                                         {
11343                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11344                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11345                                                 qglVertex3f(v[0], v[1], v[2]);
11346                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11347                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11348                                                 qglVertex3f(v[0], v[1], v[2]);
11349                                         }
11350                                 }
11351                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11352                                 {
11353                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11354                                         {
11355                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11356                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11357                                                 qglVertex3f(v[0], v[1], v[2]);
11358                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11359                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11360                                                 qglVertex3f(v[0], v[1], v[2]);
11361                                         }
11362                                 }
11363                                 qglEnd();
11364                                 CHECKGLERROR
11365                         }
11366                 }
11367                 rsurface.texture = NULL;
11368         }
11369 }
11370
11371 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11372 int r_maxsurfacelist = 0;
11373 const msurface_t **r_surfacelist = NULL;
11374 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11375 {
11376         int i, j, endj, flagsmask;
11377         dp_model_t *model = r_refdef.scene.worldmodel;
11378         msurface_t *surfaces;
11379         unsigned char *update;
11380         int numsurfacelist = 0;
11381         if (model == NULL)
11382                 return;
11383
11384         if (r_maxsurfacelist < model->num_surfaces)
11385         {
11386                 r_maxsurfacelist = model->num_surfaces;
11387                 if (r_surfacelist)
11388                         Mem_Free((msurface_t**)r_surfacelist);
11389                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11390         }
11391
11392         RSurf_ActiveWorldEntity();
11393
11394         surfaces = model->data_surfaces;
11395         update = model->brushq1.lightmapupdateflags;
11396
11397         // update light styles on this submodel
11398         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11399         {
11400                 model_brush_lightstyleinfo_t *style;
11401                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11402                 {
11403                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11404                         {
11405                                 int *list = style->surfacelist;
11406                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11407                                 for (j = 0;j < style->numsurfaces;j++)
11408                                         update[list[j]] = true;
11409                         }
11410                 }
11411         }
11412
11413         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11414
11415         if (debug)
11416         {
11417                 R_DrawDebugModel();
11418                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11419                 return;
11420         }
11421
11422         rsurface.lightmaptexture = NULL;
11423         rsurface.deluxemaptexture = NULL;
11424         rsurface.uselightmaptexture = false;
11425         rsurface.texture = NULL;
11426         rsurface.rtlight = NULL;
11427         numsurfacelist = 0;
11428         // add visible surfaces to draw list
11429         for (i = 0;i < model->nummodelsurfaces;i++)
11430         {
11431                 j = model->sortedmodelsurfaces[i];
11432                 if (r_refdef.viewcache.world_surfacevisible[j])
11433                         r_surfacelist[numsurfacelist++] = surfaces + j;
11434         }
11435         // update lightmaps if needed
11436         if (model->brushq1.firstrender)
11437         {
11438                 model->brushq1.firstrender = false;
11439                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11440                         if (update[j])
11441                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11442         }
11443         else if (update)
11444         {
11445                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11446                         if (r_refdef.viewcache.world_surfacevisible[j])
11447                                 if (update[j])
11448                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11449         }
11450         // don't do anything if there were no surfaces
11451         if (!numsurfacelist)
11452         {
11453                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11454                 return;
11455         }
11456         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11457
11458         // add to stats if desired
11459         if (r_speeds.integer && !skysurfaces && !depthonly)
11460         {
11461                 r_refdef.stats.world_surfaces += numsurfacelist;
11462                 for (j = 0;j < numsurfacelist;j++)
11463                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11464         }
11465
11466         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11467 }
11468
11469 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11470 {
11471         int i, j, endj, flagsmask;
11472         dp_model_t *model = ent->model;
11473         msurface_t *surfaces;
11474         unsigned char *update;
11475         int numsurfacelist = 0;
11476         if (model == NULL)
11477                 return;
11478
11479         if (r_maxsurfacelist < model->num_surfaces)
11480         {
11481                 r_maxsurfacelist = model->num_surfaces;
11482                 if (r_surfacelist)
11483                         Mem_Free((msurface_t **)r_surfacelist);
11484                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11485         }
11486
11487         // if the model is static it doesn't matter what value we give for
11488         // wantnormals and wanttangents, so this logic uses only rules applicable
11489         // to a model, knowing that they are meaningless otherwise
11490         if (ent == r_refdef.scene.worldentity)
11491                 RSurf_ActiveWorldEntity();
11492         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11493                 RSurf_ActiveModelEntity(ent, false, false, false);
11494         else if (prepass)
11495                 RSurf_ActiveModelEntity(ent, true, true, true);
11496         else if (depthonly)
11497         {
11498                 switch (vid.renderpath)
11499                 {
11500                 case RENDERPATH_GL20:
11501                 case RENDERPATH_D3D9:
11502                 case RENDERPATH_D3D10:
11503                 case RENDERPATH_D3D11:
11504                 case RENDERPATH_SOFT:
11505                 case RENDERPATH_GLES2:
11506                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11507                         break;
11508                 case RENDERPATH_GL11:
11509                 case RENDERPATH_GL13:
11510                 case RENDERPATH_GLES1:
11511                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11512                         break;
11513                 }
11514         }
11515         else
11516         {
11517                 switch (vid.renderpath)
11518                 {
11519                 case RENDERPATH_GL20:
11520                 case RENDERPATH_D3D9:
11521                 case RENDERPATH_D3D10:
11522                 case RENDERPATH_D3D11:
11523                 case RENDERPATH_SOFT:
11524                 case RENDERPATH_GLES2:
11525                         RSurf_ActiveModelEntity(ent, true, true, false);
11526                         break;
11527                 case RENDERPATH_GL11:
11528                 case RENDERPATH_GL13:
11529                 case RENDERPATH_GLES1:
11530                         RSurf_ActiveModelEntity(ent, true, false, false);
11531                         break;
11532                 }
11533         }
11534
11535         surfaces = model->data_surfaces;
11536         update = model->brushq1.lightmapupdateflags;
11537
11538         // update light styles
11539         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11540         {
11541                 model_brush_lightstyleinfo_t *style;
11542                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11543                 {
11544                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11545                         {
11546                                 int *list = style->surfacelist;
11547                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11548                                 for (j = 0;j < style->numsurfaces;j++)
11549                                         update[list[j]] = true;
11550                         }
11551                 }
11552         }
11553
11554         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11555
11556         if (debug)
11557         {
11558                 R_DrawDebugModel();
11559                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11560                 return;
11561         }
11562
11563         rsurface.lightmaptexture = NULL;
11564         rsurface.deluxemaptexture = NULL;
11565         rsurface.uselightmaptexture = false;
11566         rsurface.texture = NULL;
11567         rsurface.rtlight = NULL;
11568         numsurfacelist = 0;
11569         // add visible surfaces to draw list
11570         for (i = 0;i < model->nummodelsurfaces;i++)
11571                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11572         // don't do anything if there were no surfaces
11573         if (!numsurfacelist)
11574         {
11575                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11576                 return;
11577         }
11578         // update lightmaps if needed
11579         if (update)
11580         {
11581                 int updated = 0;
11582                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11583                 {
11584                         if (update[j])
11585                         {
11586                                 updated++;
11587                                 R_BuildLightMap(ent, surfaces + j);
11588                         }
11589                 }
11590         }
11591         if (update)
11592                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11593                         if (update[j])
11594                                 R_BuildLightMap(ent, surfaces + j);
11595         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11596
11597         // add to stats if desired
11598         if (r_speeds.integer && !skysurfaces && !depthonly)
11599         {
11600                 r_refdef.stats.entities_surfaces += numsurfacelist;
11601                 for (j = 0;j < numsurfacelist;j++)
11602                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11603         }
11604
11605         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11606 }
11607
11608 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11609 {
11610         static texture_t texture;
11611         static msurface_t surface;
11612         const msurface_t *surfacelist = &surface;
11613
11614         // fake enough texture and surface state to render this geometry
11615
11616         texture.update_lastrenderframe = -1; // regenerate this texture
11617         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11618         texture.currentskinframe = skinframe;
11619         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11620         texture.offsetmapping = OFFSETMAPPING_OFF;
11621         texture.offsetscale = 1;
11622         texture.specularscalemod = 1;
11623         texture.specularpowermod = 1;
11624
11625         surface.texture = &texture;
11626         surface.num_triangles = numtriangles;
11627         surface.num_firsttriangle = firsttriangle;
11628         surface.num_vertices = numvertices;
11629         surface.num_firstvertex = firstvertex;
11630
11631         // now render it
11632         rsurface.texture = R_GetCurrentTexture(surface.texture);
11633         rsurface.lightmaptexture = NULL;
11634         rsurface.deluxemaptexture = NULL;
11635         rsurface.uselightmaptexture = false;
11636         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11637 }
11638
11639 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)
11640 {
11641         static msurface_t surface;
11642         const msurface_t *surfacelist = &surface;
11643
11644         // fake enough texture and surface state to render this geometry
11645         surface.texture = texture;
11646         surface.num_triangles = numtriangles;
11647         surface.num_firsttriangle = firsttriangle;
11648         surface.num_vertices = numvertices;
11649         surface.num_firstvertex = firstvertex;
11650
11651         // now render it
11652         rsurface.texture = R_GetCurrentTexture(surface.texture);
11653         rsurface.lightmaptexture = NULL;
11654         rsurface.deluxemaptexture = NULL;
11655         rsurface.uselightmaptexture = false;
11656         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11657 }