]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added "loadcubemap" builtin to allow preload cubemaps level can use, added experiment...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
210 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
211 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
212 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
213 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
214 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
215 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
216 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
217
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
220
221 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."};
222
223 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)"};
224
225 extern cvar_t v_glslgamma;
226
227 extern qboolean v_flipped_state;
228
229 static struct r_bloomstate_s
230 {
231         qboolean enabled;
232         qboolean hdr;
233
234         int bloomwidth, bloomheight;
235
236         textype_t texturetype;
237         int viewfbo; // used to check if r_viewfbo cvar has changed
238
239         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
242
243         int screentexturewidth, screentextureheight;
244         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
245
246         int bloomtexturewidth, bloomtextureheight;
247         rtexture_t *texture_bloom;
248
249         // arrays for rendering the screen passes
250         float screentexcoord2f[8];
251         float bloomtexcoord2f[8];
252         float offsettexcoord2f[8];
253
254         r_viewport_t viewport;
255 }
256 r_bloomstate;
257
258 r_waterstate_t r_waterstate;
259
260 /// shadow volume bsp struct with automatically growing nodes buffer
261 svbsp_t r_svbsp;
262
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
276
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
279 {
280         char basename[64];
281         rtexture_t *texture;
282 }
283 cubemapinfo_t;
284
285 int r_texture_numcubemaps;
286 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
287
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
291
292 typedef struct r_qwskincache_s
293 {
294         char name[MAX_QPATH];
295         skinframe_t *skinframe;
296 }
297 r_qwskincache_t;
298
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
301
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
306 {
307         0, 0, 0,
308         1, 0, 0,
309         1, 1, 0,
310         0, 1, 0
311 };
312 const float r_d3dscreenvertex3f[12] =
313 {
314         0, 1, 0,
315         1, 1, 0,
316         1, 0, 0,
317         0, 0, 0
318 };
319
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
321 {
322         int i;
323         for (i = 0;i < verts;i++)
324         {
325                 out[0] = in[0] * r;
326                 out[1] = in[1] * g;
327                 out[2] = in[2] * b;
328                 out[3] = in[3];
329                 in += 4;
330                 out += 4;
331         }
332 }
333
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = r;
340                 out[1] = g;
341                 out[2] = b;
342                 out[3] = a;
343                 out += 4;
344         }
345 }
346
347 // FIXME: move this to client?
348 void FOG_clear(void)
349 {
350         if (gamemode == GAME_NEHAHRA)
351         {
352                 Cvar_Set("gl_fogenable", "0");
353                 Cvar_Set("gl_fogdensity", "0.2");
354                 Cvar_Set("gl_fogred", "0.3");
355                 Cvar_Set("gl_foggreen", "0.3");
356                 Cvar_Set("gl_fogblue", "0.3");
357         }
358         r_refdef.fog_density = 0;
359         r_refdef.fog_red = 0;
360         r_refdef.fog_green = 0;
361         r_refdef.fog_blue = 0;
362         r_refdef.fog_alpha = 1;
363         r_refdef.fog_start = 0;
364         r_refdef.fog_end = 16384;
365         r_refdef.fog_height = 1<<30;
366         r_refdef.fog_fadedepth = 128;
367         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
368 }
369
370 static void R_BuildBlankTextures(void)
371 {
372         unsigned char data[4];
373         data[2] = 128; // normal X
374         data[1] = 128; // normal Y
375         data[0] = 255; // normal Z
376         data[3] = 128; // height
377         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
378         data[0] = 255;
379         data[1] = 255;
380         data[2] = 255;
381         data[3] = 255;
382         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
383         data[0] = 128;
384         data[1] = 128;
385         data[2] = 128;
386         data[3] = 255;
387         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 0;
389         data[1] = 0;
390         data[2] = 0;
391         data[3] = 255;
392         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 }
394
395 static void R_BuildNoTexture(void)
396 {
397         int x, y;
398         unsigned char pix[16][16][4];
399         // this makes a light grey/dark grey checkerboard texture
400         for (y = 0;y < 16;y++)
401         {
402                 for (x = 0;x < 16;x++)
403                 {
404                         if ((y < 8) ^ (x < 8))
405                         {
406                                 pix[y][x][0] = 128;
407                                 pix[y][x][1] = 128;
408                                 pix[y][x][2] = 128;
409                                 pix[y][x][3] = 255;
410                         }
411                         else
412                         {
413                                 pix[y][x][0] = 64;
414                                 pix[y][x][1] = 64;
415                                 pix[y][x][2] = 64;
416                                 pix[y][x][3] = 255;
417                         }
418                 }
419         }
420         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
421 }
422
423 static void R_BuildWhiteCube(void)
424 {
425         unsigned char data[6*1*1*4];
426         memset(data, 255, sizeof(data));
427         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
428 }
429
430 static void R_BuildNormalizationCube(void)
431 {
432         int x, y, side;
433         vec3_t v;
434         vec_t s, t, intensity;
435 #define NORMSIZE 64
436         unsigned char *data;
437         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438         for (side = 0;side < 6;side++)
439         {
440                 for (y = 0;y < NORMSIZE;y++)
441                 {
442                         for (x = 0;x < NORMSIZE;x++)
443                         {
444                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 switch(side)
447                                 {
448                                 default:
449                                 case 0:
450                                         v[0] = 1;
451                                         v[1] = -t;
452                                         v[2] = -s;
453                                         break;
454                                 case 1:
455                                         v[0] = -1;
456                                         v[1] = -t;
457                                         v[2] = s;
458                                         break;
459                                 case 2:
460                                         v[0] = s;
461                                         v[1] = 1;
462                                         v[2] = t;
463                                         break;
464                                 case 3:
465                                         v[0] = s;
466                                         v[1] = -1;
467                                         v[2] = -t;
468                                         break;
469                                 case 4:
470                                         v[0] = s;
471                                         v[1] = -t;
472                                         v[2] = 1;
473                                         break;
474                                 case 5:
475                                         v[0] = -s;
476                                         v[1] = -t;
477                                         v[2] = -1;
478                                         break;
479                                 }
480                                 intensity = 127.0f / sqrt(DotProduct(v, v));
481                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484                                 data[((side*64+y)*64+x)*4+3] = 255;
485                         }
486                 }
487         }
488         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
489         Mem_Free(data);
490 }
491
492 static void R_BuildFogTexture(void)
493 {
494         int x, b;
495 #define FOGWIDTH 256
496         unsigned char data1[FOGWIDTH][4];
497         //unsigned char data2[FOGWIDTH][4];
498         double d, r, alpha;
499
500         r_refdef.fogmasktable_start = r_refdef.fog_start;
501         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502         r_refdef.fogmasktable_range = r_refdef.fogrange;
503         r_refdef.fogmasktable_density = r_refdef.fog_density;
504
505         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
507         {
508                 d = (x * r - r_refdef.fogmasktable_start);
509                 if(developer_extra.integer)
510                         Con_DPrintf("%f ", d);
511                 d = max(0, d);
512                 if (r_fog_exp2.integer)
513                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
514                 else
515                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516                 if(developer_extra.integer)
517                         Con_DPrintf(" : %f ", alpha);
518                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519                 if(developer_extra.integer)
520                         Con_DPrintf(" = %f\n", alpha);
521                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
522         }
523
524         for (x = 0;x < FOGWIDTH;x++)
525         {
526                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
527                 data1[x][0] = b;
528                 data1[x][1] = b;
529                 data1[x][2] = b;
530                 data1[x][3] = 255;
531                 //data2[x][0] = 255 - b;
532                 //data2[x][1] = 255 - b;
533                 //data2[x][2] = 255 - b;
534                 //data2[x][3] = 255;
535         }
536         if (r_texture_fogattenuation)
537         {
538                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540         }
541         else
542         {
543                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
545         }
546 }
547
548 static void R_BuildFogHeightTexture(void)
549 {
550         unsigned char *inpixels;
551         int size;
552         int x;
553         int y;
554         int j;
555         float c[4];
556         float f;
557         inpixels = NULL;
558         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559         if (r_refdef.fogheighttexturename[0])
560                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
561         if (!inpixels)
562         {
563                 r_refdef.fog_height_tablesize = 0;
564                 if (r_texture_fogheighttexture)
565                         R_FreeTexture(r_texture_fogheighttexture);
566                 r_texture_fogheighttexture = NULL;
567                 if (r_refdef.fog_height_table2d)
568                         Mem_Free(r_refdef.fog_height_table2d);
569                 r_refdef.fog_height_table2d = NULL;
570                 if (r_refdef.fog_height_table1d)
571                         Mem_Free(r_refdef.fog_height_table1d);
572                 r_refdef.fog_height_table1d = NULL;
573                 return;
574         }
575         size = image_width;
576         r_refdef.fog_height_tablesize = size;
577         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
580         Mem_Free(inpixels);
581         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
582         // average fog color table accounting for every fog layer between a point
583         // and the camera.  (Note: attenuation is handled separately!)
584         for (y = 0;y < size;y++)
585         {
586                 for (x = 0;x < size;x++)
587                 {
588                         Vector4Clear(c);
589                         f = 0;
590                         if (x < y)
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                         else
599                         {
600                                 for (j = x;j >= y;j--)
601                                 {
602                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
603                                         f++;
604                                 }
605                         }
606                         f = 1.0f / f;
607                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
611                 }
612         }
613         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
614 }
615
616 //=======================================================================================================================================================
617
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
620 ;
621
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
624 ;
625
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
628
629 //=======================================================================================================================================================
630
631 typedef struct shaderpermutationinfo_s
632 {
633         const char *pretext;
634         const char *name;
635 }
636 shaderpermutationinfo_t;
637
638 typedef struct shadermodeinfo_s
639 {
640         const char *vertexfilename;
641         const char *geometryfilename;
642         const char *fragmentfilename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676         {"#define USEALPHAKILL\n", " alphakill"},
677         {"#define USEREFLECTCUBE\n", " reflectcube"},
678         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679         {"#define USEBOUNCEGRID\n", " bouncegrid"},
680         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 };
682
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
705 {
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 };
723
724 struct r_glsl_permutation_s;
725 typedef struct r_glsl_permutation_s
726 {
727         /// hash lookup data
728         struct r_glsl_permutation_s *hashnext;
729         unsigned int mode;
730         unsigned int permutation;
731
732         /// indicates if we have tried compiling this permutation already
733         qboolean compiled;
734         /// 0 if compilation failed
735         int program;
736         // texture units assigned to each detected uniform
737         int tex_Texture_First;
738         int tex_Texture_Second;
739         int tex_Texture_GammaRamps;
740         int tex_Texture_Normal;
741         int tex_Texture_Color;
742         int tex_Texture_Gloss;
743         int tex_Texture_Glow;
744         int tex_Texture_SecondaryNormal;
745         int tex_Texture_SecondaryColor;
746         int tex_Texture_SecondaryGloss;
747         int tex_Texture_SecondaryGlow;
748         int tex_Texture_Pants;
749         int tex_Texture_Shirt;
750         int tex_Texture_FogHeightTexture;
751         int tex_Texture_FogMask;
752         int tex_Texture_Lightmap;
753         int tex_Texture_Deluxemap;
754         int tex_Texture_Attenuation;
755         int tex_Texture_Cube;
756         int tex_Texture_Refraction;
757         int tex_Texture_Reflection;
758         int tex_Texture_ShadowMap2D;
759         int tex_Texture_CubeProjection;
760         int tex_Texture_ScreenDepth;
761         int tex_Texture_ScreenNormalMap;
762         int tex_Texture_ScreenDiffuse;
763         int tex_Texture_ScreenSpecular;
764         int tex_Texture_ReflectMask;
765         int tex_Texture_ReflectCube;
766         int tex_Texture_BounceGrid;
767         /// locations of detected uniforms in program object, or -1 if not found
768         int loc_Texture_First;
769         int loc_Texture_Second;
770         int loc_Texture_GammaRamps;
771         int loc_Texture_Normal;
772         int loc_Texture_Color;
773         int loc_Texture_Gloss;
774         int loc_Texture_Glow;
775         int loc_Texture_SecondaryNormal;
776         int loc_Texture_SecondaryColor;
777         int loc_Texture_SecondaryGloss;
778         int loc_Texture_SecondaryGlow;
779         int loc_Texture_Pants;
780         int loc_Texture_Shirt;
781         int loc_Texture_FogHeightTexture;
782         int loc_Texture_FogMask;
783         int loc_Texture_Lightmap;
784         int loc_Texture_Deluxemap;
785         int loc_Texture_Attenuation;
786         int loc_Texture_Cube;
787         int loc_Texture_Refraction;
788         int loc_Texture_Reflection;
789         int loc_Texture_ShadowMap2D;
790         int loc_Texture_CubeProjection;
791         int loc_Texture_ScreenDepth;
792         int loc_Texture_ScreenNormalMap;
793         int loc_Texture_ScreenDiffuse;
794         int loc_Texture_ScreenSpecular;
795         int loc_Texture_ReflectMask;
796         int loc_Texture_ReflectCube;
797         int loc_Texture_BounceGrid;
798         int loc_Alpha;
799         int loc_BloomBlur_Parameters;
800         int loc_ClientTime;
801         int loc_Color_Ambient;
802         int loc_Color_Diffuse;
803         int loc_Color_Specular;
804         int loc_Color_Glow;
805         int loc_Color_Pants;
806         int loc_Color_Shirt;
807         int loc_DeferredColor_Ambient;
808         int loc_DeferredColor_Diffuse;
809         int loc_DeferredColor_Specular;
810         int loc_DeferredMod_Diffuse;
811         int loc_DeferredMod_Specular;
812         int loc_DistortScaleRefractReflect;
813         int loc_EyePosition;
814         int loc_FogColor;
815         int loc_FogHeightFade;
816         int loc_FogPlane;
817         int loc_FogPlaneViewDist;
818         int loc_FogRangeRecip;
819         int loc_LightColor;
820         int loc_LightDir;
821         int loc_LightPosition;
822         int loc_OffsetMapping_ScaleSteps;
823         int loc_PixelSize;
824         int loc_ReflectColor;
825         int loc_ReflectFactor;
826         int loc_ReflectOffset;
827         int loc_RefractColor;
828         int loc_Saturation;
829         int loc_ScreenCenterRefractReflect;
830         int loc_ScreenScaleRefractReflect;
831         int loc_ScreenToDepth;
832         int loc_ShadowMap_Parameters;
833         int loc_ShadowMap_TextureScale;
834         int loc_SpecularPower;
835         int loc_UserVec1;
836         int loc_UserVec2;
837         int loc_UserVec3;
838         int loc_UserVec4;
839         int loc_ViewTintColor;
840         int loc_ViewToLight;
841         int loc_ModelToLight;
842         int loc_TexMatrix;
843         int loc_BackgroundTexMatrix;
844         int loc_ModelViewProjectionMatrix;
845         int loc_ModelViewMatrix;
846         int loc_PixelToScreenTexCoord;
847         int loc_ModelToReflectCube;
848         int loc_ShadowMapMatrix;
849         int loc_BloomColorSubtract;
850         int loc_NormalmapScrollBlend;
851         int loc_BounceGridMatrix;
852         int loc_BounceGridIntensity;
853 }
854 r_glsl_permutation_t;
855
856 #define SHADERPERMUTATION_HASHSIZE 256
857
858
859 // non-degradable "lightweight" shader parameters to keep the permutations simpler
860 // these can NOT degrade! only use for simple stuff
861 enum
862 {
863         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
864         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
865         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
868         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
869         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
870 };
871 #define SHADERSTATICPARMS_COUNT 7
872
873 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
874 static int shaderstaticparms_count = 0;
875
876 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
877 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 qboolean R_CompileShader_CheckStaticParms(void)
879 {
880         static int r_compileshader_staticparms_save[1];
881         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
882         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883
884         // detect all
885         if (r_glsl_saturation_redcompensate.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
887         if (r_glsl_vertextextureblend_usebothalphas.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
889         if (r_shadow_glossexact.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
891         if (r_glsl_postprocess.integer)
892         {
893                 if (r_glsl_postprocess_uservec1_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
895                 if (r_glsl_postprocess_uservec2_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
897                 if (r_glsl_postprocess_uservec3_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
899                 if (r_glsl_postprocess_uservec4_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
901         }
902         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 }
904
905 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
906         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
908         else \
909                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
910 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
911 {
912         shaderstaticparms_count = 0;
913
914         // emit all
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 }
923
924 /// information about each possible shader permutation
925 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
926 /// currently selected permutation
927 r_glsl_permutation_t *r_glsl_permutation;
928 /// storage for permutations linked in the hash table
929 memexpandablearray_t r_glsl_permutationarray;
930
931 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
932 {
933         //unsigned int hashdepth = 0;
934         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
935         r_glsl_permutation_t *p;
936         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
937         {
938                 if (p->mode == mode && p->permutation == permutation)
939                 {
940                         //if (hashdepth > 10)
941                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
942                         return p;
943                 }
944                 //hashdepth++;
945         }
946         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
947         p->mode = mode;
948         p->permutation = permutation;
949         p->hashnext = r_glsl_permutationhash[mode][hashindex];
950         r_glsl_permutationhash[mode][hashindex] = p;
951         //if (hashdepth > 10)
952         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
953         return p;
954 }
955
956 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 {
958         char *shaderstring;
959         if (!filename || !filename[0])
960                 return NULL;
961         if (!strcmp(filename, "glsl/default.glsl"))
962         {
963                 if (!glslshaderstring)
964                 {
965                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
966                         if (glslshaderstring)
967                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
968                         else
969                                 glslshaderstring = (char *)builtinshaderstring;
970                 }
971                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
972                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973                 return shaderstring;
974         }
975         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976         if (shaderstring)
977         {
978                 if (printfromdisknotice)
979                         Con_DPrintf("from disk %s... ", filename);
980                 return shaderstring;
981         }
982         return shaderstring;
983 }
984
985 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
986 {
987         int i;
988         int sampler;
989         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
990         char *vertexstring, *geometrystring, *fragmentstring;
991         char permutationname[256];
992         int vertstrings_count = 0;
993         int geomstrings_count = 0;
994         int fragstrings_count = 0;
995         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998
999         if (p->compiled)
1000                 return;
1001         p->compiled = true;
1002         p->program = 0;
1003
1004         permutationname[0] = 0;
1005         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1006         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1007         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1008
1009         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1010
1011         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1012         if(vid.support.gl20shaders130)
1013         {
1014                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1015                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1016                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1017                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1018                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1019                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020         }
1021
1022         // the first pretext is which type of shader to compile as
1023         // (later these will all be bound together as a program object)
1024         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1025         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1026         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1027
1028         // the second pretext is the mode (for example a light source)
1029         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1030         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1031         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1032         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1033
1034         // now add all the permutation pretexts
1035         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1036         {
1037                 if (permutation & (1<<i))
1038                 {
1039                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1042                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1043                 }
1044                 else
1045                 {
1046                         // keep line numbers correct
1047                         vertstrings_list[vertstrings_count++] = "\n";
1048                         geomstrings_list[geomstrings_count++] = "\n";
1049                         fragstrings_list[fragstrings_count++] = "\n";
1050                 }
1051         }
1052
1053         // add static parms
1054         R_CompileShader_AddStaticParms(mode, permutation);
1055         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         vertstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         geomstrings_count += shaderstaticparms_count;
1059         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         fragstrings_count += shaderstaticparms_count;
1061
1062         // now append the shader text itself
1063         vertstrings_list[vertstrings_count++] = vertexstring;
1064         geomstrings_list[geomstrings_count++] = geometrystring;
1065         fragstrings_list[fragstrings_count++] = fragmentstring;
1066
1067         // if any sources were NULL, clear the respective list
1068         if (!vertexstring)
1069                 vertstrings_count = 0;
1070         if (!geometrystring)
1071                 geomstrings_count = 0;
1072         if (!fragmentstring)
1073                 fragstrings_count = 0;
1074
1075         // compile the shader program
1076         if (vertstrings_count + geomstrings_count + fragstrings_count)
1077                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1078         if (p->program)
1079         {
1080                 CHECKGLERROR
1081                 qglUseProgram(p->program);CHECKGLERROR
1082                 // look up all the uniform variable names we care about, so we don't
1083                 // have to look them up every time we set them
1084
1085                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1086                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1087                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1088                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1089                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1090                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1091                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1092                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1093                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1094                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1095                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1096                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1097                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1098                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1099                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1100                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1101                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1102                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1103                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1104                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1105                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1106                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1107                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1108                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1109                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1110                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1111                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1112                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1113                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1114                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1115                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1116                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1117                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1118                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1119                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1120                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1121                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1122                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1123                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1124                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1125                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1126                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1127                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1128                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1129                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1130                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1131                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1132                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1133                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1134                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1135                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1136                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1137                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1138                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1139                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1140                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1141                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1142                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1143                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1144                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1145                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1146                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1147                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1148                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1149                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1150                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1151                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1152                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1153                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1154                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1155                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1156                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1157                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1158                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1159                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1160                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1161                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1162                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1163                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1164                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1165                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1166                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1167                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1168                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1169                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1170                 // initialize the samplers to refer to the texture units we use
1171                 p->tex_Texture_First = -1;
1172                 p->tex_Texture_Second = -1;
1173                 p->tex_Texture_GammaRamps = -1;
1174                 p->tex_Texture_Normal = -1;
1175                 p->tex_Texture_Color = -1;
1176                 p->tex_Texture_Gloss = -1;
1177                 p->tex_Texture_Glow = -1;
1178                 p->tex_Texture_SecondaryNormal = -1;
1179                 p->tex_Texture_SecondaryColor = -1;
1180                 p->tex_Texture_SecondaryGloss = -1;
1181                 p->tex_Texture_SecondaryGlow = -1;
1182                 p->tex_Texture_Pants = -1;
1183                 p->tex_Texture_Shirt = -1;
1184                 p->tex_Texture_FogHeightTexture = -1;
1185                 p->tex_Texture_FogMask = -1;
1186                 p->tex_Texture_Lightmap = -1;
1187                 p->tex_Texture_Deluxemap = -1;
1188                 p->tex_Texture_Attenuation = -1;
1189                 p->tex_Texture_Cube = -1;
1190                 p->tex_Texture_Refraction = -1;
1191                 p->tex_Texture_Reflection = -1;
1192                 p->tex_Texture_ShadowMap2D = -1;
1193                 p->tex_Texture_CubeProjection = -1;
1194                 p->tex_Texture_ScreenDepth = -1;
1195                 p->tex_Texture_ScreenNormalMap = -1;
1196                 p->tex_Texture_ScreenDiffuse = -1;
1197                 p->tex_Texture_ScreenSpecular = -1;
1198                 p->tex_Texture_ReflectMask = -1;
1199                 p->tex_Texture_ReflectCube = -1;
1200                 p->tex_Texture_BounceGrid = -1;
1201                 sampler = 0;
1202                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1203                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1204                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1205                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1206                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1207                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1208                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1213                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1214                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1215                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1216                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1217                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1218                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1219                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1220                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1221                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1222                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1223                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1224                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1229                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1230                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1231                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1232                 CHECKGLERROR
1233                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234         }
1235         else
1236                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1237
1238         // free the strings
1239         if (vertexstring)
1240                 Mem_Free(vertexstring);
1241         if (geometrystring)
1242                 Mem_Free(geometrystring);
1243         if (fragmentstring)
1244                 Mem_Free(fragmentstring);
1245 }
1246
1247 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1248 {
1249         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1250         if (r_glsl_permutation != perm)
1251         {
1252                 r_glsl_permutation = perm;
1253                 if (!r_glsl_permutation->program)
1254                 {
1255                         if (!r_glsl_permutation->compiled)
1256                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1257                         if (!r_glsl_permutation->program)
1258                         {
1259                                 // remove features until we find a valid permutation
1260                                 int i;
1261                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1262                                 {
1263                                         // reduce i more quickly whenever it would not remove any bits
1264                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1265                                         if (!(permutation & j))
1266                                                 continue;
1267                                         permutation -= j;
1268                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1269                                         if (!r_glsl_permutation->compiled)
1270                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1271                                         if (r_glsl_permutation->program)
1272                                                 break;
1273                                 }
1274                                 if (i >= SHADERPERMUTATION_COUNT)
1275                                 {
1276                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1277                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1278                                         qglUseProgram(0);CHECKGLERROR
1279                                         return; // no bit left to clear, entire mode is broken
1280                                 }
1281                         }
1282                 }
1283                 CHECKGLERROR
1284                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1285         }
1286         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1287         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1288         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1289 }
1290
1291 #ifdef SUPPORTD3D
1292
1293 #ifdef SUPPORTD3D
1294 #include <d3d9.h>
1295 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1296 extern D3DCAPS9 vid_d3d9caps;
1297 #endif
1298
1299 struct r_hlsl_permutation_s;
1300 typedef struct r_hlsl_permutation_s
1301 {
1302         /// hash lookup data
1303         struct r_hlsl_permutation_s *hashnext;
1304         unsigned int mode;
1305         unsigned int permutation;
1306
1307         /// indicates if we have tried compiling this permutation already
1308         qboolean compiled;
1309         /// NULL if compilation failed
1310         IDirect3DVertexShader9 *vertexshader;
1311         IDirect3DPixelShader9 *pixelshader;
1312 }
1313 r_hlsl_permutation_t;
1314
1315 typedef enum D3DVSREGISTER_e
1316 {
1317         D3DVSREGISTER_TexMatrix = 0, // float4x4
1318         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1319         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1320         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1321         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1322         D3DVSREGISTER_ModelToLight = 20, // float4x4
1323         D3DVSREGISTER_EyePosition = 24,
1324         D3DVSREGISTER_FogPlane = 25,
1325         D3DVSREGISTER_LightDir = 26,
1326         D3DVSREGISTER_LightPosition = 27,
1327 }
1328 D3DVSREGISTER_t;
1329
1330 typedef enum D3DPSREGISTER_e
1331 {
1332         D3DPSREGISTER_Alpha = 0,
1333         D3DPSREGISTER_BloomBlur_Parameters = 1,
1334         D3DPSREGISTER_ClientTime = 2,
1335         D3DPSREGISTER_Color_Ambient = 3,
1336         D3DPSREGISTER_Color_Diffuse = 4,
1337         D3DPSREGISTER_Color_Specular = 5,
1338         D3DPSREGISTER_Color_Glow = 6,
1339         D3DPSREGISTER_Color_Pants = 7,
1340         D3DPSREGISTER_Color_Shirt = 8,
1341         D3DPSREGISTER_DeferredColor_Ambient = 9,
1342         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1343         D3DPSREGISTER_DeferredColor_Specular = 11,
1344         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1345         D3DPSREGISTER_DeferredMod_Specular = 13,
1346         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1347         D3DPSREGISTER_EyePosition = 15, // unused
1348         D3DPSREGISTER_FogColor = 16,
1349         D3DPSREGISTER_FogHeightFade = 17,
1350         D3DPSREGISTER_FogPlane = 18,
1351         D3DPSREGISTER_FogPlaneViewDist = 19,
1352         D3DPSREGISTER_FogRangeRecip = 20,
1353         D3DPSREGISTER_LightColor = 21,
1354         D3DPSREGISTER_LightDir = 22, // unused
1355         D3DPSREGISTER_LightPosition = 23,
1356         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1357         D3DPSREGISTER_PixelSize = 25,
1358         D3DPSREGISTER_ReflectColor = 26,
1359         D3DPSREGISTER_ReflectFactor = 27,
1360         D3DPSREGISTER_ReflectOffset = 28,
1361         D3DPSREGISTER_RefractColor = 29,
1362         D3DPSREGISTER_Saturation = 30,
1363         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1364         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1365         D3DPSREGISTER_ScreenToDepth = 33,
1366         D3DPSREGISTER_ShadowMap_Parameters = 34,
1367         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1368         D3DPSREGISTER_SpecularPower = 36,
1369         D3DPSREGISTER_UserVec1 = 37,
1370         D3DPSREGISTER_UserVec2 = 38,
1371         D3DPSREGISTER_UserVec3 = 39,
1372         D3DPSREGISTER_UserVec4 = 40,
1373         D3DPSREGISTER_ViewTintColor = 41,
1374         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1375         D3DPSREGISTER_BloomColorSubtract = 43,
1376         D3DPSREGISTER_ViewToLight = 44, // float4x4
1377         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1378         D3DPSREGISTER_NormalmapScrollBlend = 52,
1379         // next at 53
1380 }
1381 D3DPSREGISTER_t;
1382
1383 /// information about each possible shader permutation
1384 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1385 /// currently selected permutation
1386 r_hlsl_permutation_t *r_hlsl_permutation;
1387 /// storage for permutations linked in the hash table
1388 memexpandablearray_t r_hlsl_permutationarray;
1389
1390 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1391 {
1392         //unsigned int hashdepth = 0;
1393         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1394         r_hlsl_permutation_t *p;
1395         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1396         {
1397                 if (p->mode == mode && p->permutation == permutation)
1398                 {
1399                         //if (hashdepth > 10)
1400                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1401                         return p;
1402                 }
1403                 //hashdepth++;
1404         }
1405         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1406         p->mode = mode;
1407         p->permutation = permutation;
1408         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1409         r_hlsl_permutationhash[mode][hashindex] = p;
1410         //if (hashdepth > 10)
1411         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1412         return p;
1413 }
1414
1415 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 {
1417         char *shaderstring;
1418         if (!filename || !filename[0])
1419                 return NULL;
1420         if (!strcmp(filename, "hlsl/default.hlsl"))
1421         {
1422                 if (!hlslshaderstring)
1423                 {
1424                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425                         if (hlslshaderstring)
1426                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1427                         else
1428                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1429                 }
1430                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1431                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1432                 return shaderstring;
1433         }
1434         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435         if (shaderstring)
1436         {
1437                 if (printfromdisknotice)
1438                         Con_DPrintf("from disk %s... ", filename);
1439                 return shaderstring;
1440         }
1441         return shaderstring;
1442 }
1443
1444 #include <d3dx9.h>
1445 //#include <d3dx9shader.h>
1446 //#include <d3dx9mesh.h>
1447
1448 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1449 {
1450         DWORD *vsbin = NULL;
1451         DWORD *psbin = NULL;
1452         fs_offset_t vsbinsize;
1453         fs_offset_t psbinsize;
1454 //      IDirect3DVertexShader9 *vs = NULL;
1455 //      IDirect3DPixelShader9 *ps = NULL;
1456         ID3DXBuffer *vslog = NULL;
1457         ID3DXBuffer *vsbuffer = NULL;
1458         ID3DXConstantTable *vsconstanttable = NULL;
1459         ID3DXBuffer *pslog = NULL;
1460         ID3DXBuffer *psbuffer = NULL;
1461         ID3DXConstantTable *psconstanttable = NULL;
1462         int vsresult = 0;
1463         int psresult = 0;
1464         char temp[MAX_INPUTLINE];
1465         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1466         qboolean debugshader = gl_paranoid.integer != 0;
1467         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469         if (!debugshader)
1470         {
1471                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1472                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1473         }
1474         if ((!vsbin && vertstring) || (!psbin && fragstring))
1475         {
1476                 const char* dllnames_d3dx9 [] =
1477                 {
1478                         "d3dx9_43.dll",
1479                         "d3dx9_42.dll",
1480                         "d3dx9_41.dll",
1481                         "d3dx9_40.dll",
1482                         "d3dx9_39.dll",
1483                         "d3dx9_38.dll",
1484                         "d3dx9_37.dll",
1485                         "d3dx9_36.dll",
1486                         "d3dx9_35.dll",
1487                         "d3dx9_34.dll",
1488                         "d3dx9_33.dll",
1489                         "d3dx9_32.dll",
1490                         "d3dx9_31.dll",
1491                         "d3dx9_30.dll",
1492                         "d3dx9_29.dll",
1493                         "d3dx9_28.dll",
1494                         "d3dx9_27.dll",
1495                         "d3dx9_26.dll",
1496                         "d3dx9_25.dll",
1497                         "d3dx9_24.dll",
1498                         NULL
1499                 };
1500                 dllhandle_t d3dx9_dll = NULL;
1501                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1503                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504                 dllfunction_t d3dx9_dllfuncs[] =
1505                 {
1506                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1507                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1508                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1509                         {NULL, NULL}
1510                 };
1511                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1512                 {
1513                         DWORD shaderflags = 0;
1514                         if (debugshader)
1515                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1516                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1517                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1518                         if (vertstring && vertstring[0])
1519                         {
1520                                 if (debugshader)
1521                                 {
1522 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1523 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1524                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1525                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526                                 }
1527                                 else
1528                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529                                 if (vsbuffer)
1530                                 {
1531                                         vsbinsize = vsbuffer->GetBufferSize();
1532                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1533                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1534                                         vsbuffer->Release();
1535                                 }
1536                                 if (vslog)
1537                                 {
1538                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1539                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1540                                         vslog->Release();
1541                                 }
1542                         }
1543                         if (fragstring && fragstring[0])
1544                         {
1545                                 if (debugshader)
1546                                 {
1547 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1548 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1549                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1550                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551                                 }
1552                                 else
1553                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554                                 if (psbuffer)
1555                                 {
1556                                         psbinsize = psbuffer->GetBufferSize();
1557                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1558                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1559                                         psbuffer->Release();
1560                                 }
1561                                 if (pslog)
1562                                 {
1563                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1564                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1565                                         pslog->Release();
1566                                 }
1567                         }
1568                         Sys_UnloadLibrary(&d3dx9_dll);
1569                 }
1570                 else
1571                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1572         }
1573         if (vsbin && psbin)
1574         {
1575                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1576                 if (FAILED(vsresult))
1577                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1578                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1579                 if (FAILED(psresult))
1580                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1581         }
1582         // free the shader data
1583         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1584         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 }
1586
1587 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 {
1589         int i;
1590         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1591         int vertstring_length = 0;
1592         int geomstring_length = 0;
1593         int fragstring_length = 0;
1594         char *t;
1595         char *vertexstring, *geometrystring, *fragmentstring;
1596         char *vertstring, *geomstring, *fragstring;
1597         char permutationname[256];
1598         char cachename[256];
1599         int vertstrings_count = 0;
1600         int geomstrings_count = 0;
1601         int fragstrings_count = 0;
1602         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605
1606         if (p->compiled)
1607                 return;
1608         p->compiled = true;
1609         p->vertexshader = NULL;
1610         p->pixelshader = NULL;
1611
1612         permutationname[0] = 0;
1613         cachename[0] = 0;
1614         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1615         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1616         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1617
1618         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1619         strlcat(cachename, "hlsl/", sizeof(cachename));
1620
1621         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1622         vertstrings_count = 0;
1623         geomstrings_count = 0;
1624         fragstrings_count = 0;
1625         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1626         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1627         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1628
1629         // the first pretext is which type of shader to compile as
1630         // (later these will all be bound together as a program object)
1631         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1632         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1633         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1634
1635         // the second pretext is the mode (for example a light source)
1636         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1637         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1638         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1639         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1640         strlcat(cachename, modeinfo->name, sizeof(cachename));
1641
1642         // now add all the permutation pretexts
1643         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1644         {
1645                 if (permutation & (1<<i))
1646                 {
1647                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1650                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1651                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1652                 }
1653                 else
1654                 {
1655                         // keep line numbers correct
1656                         vertstrings_list[vertstrings_count++] = "\n";
1657                         geomstrings_list[geomstrings_count++] = "\n";
1658                         fragstrings_list[fragstrings_count++] = "\n";
1659                 }
1660         }
1661
1662         // add static parms
1663         R_CompileShader_AddStaticParms(mode, permutation);
1664         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         vertstrings_count += shaderstaticparms_count;
1666         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         geomstrings_count += shaderstaticparms_count;
1668         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         fragstrings_count += shaderstaticparms_count;
1670
1671         // replace spaces in the cachename with _ characters
1672         for (i = 0;cachename[i];i++)
1673                 if (cachename[i] == ' ')
1674                         cachename[i] = '_';
1675
1676         // now append the shader text itself
1677         vertstrings_list[vertstrings_count++] = vertexstring;
1678         geomstrings_list[geomstrings_count++] = geometrystring;
1679         fragstrings_list[fragstrings_count++] = fragmentstring;
1680
1681         // if any sources were NULL, clear the respective list
1682         if (!vertexstring)
1683                 vertstrings_count = 0;
1684         if (!geometrystring)
1685                 geomstrings_count = 0;
1686         if (!fragmentstring)
1687                 fragstrings_count = 0;
1688
1689         vertstring_length = 0;
1690         for (i = 0;i < vertstrings_count;i++)
1691                 vertstring_length += strlen(vertstrings_list[i]);
1692         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1693         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1694                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1695
1696         geomstring_length = 0;
1697         for (i = 0;i < geomstrings_count;i++)
1698                 geomstring_length += strlen(geomstrings_list[i]);
1699         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1700         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1701                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1702
1703         fragstring_length = 0;
1704         for (i = 0;i < fragstrings_count;i++)
1705                 fragstring_length += strlen(fragstrings_list[i]);
1706         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1707         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1708                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1709
1710         // try to load the cached shader, or generate one
1711         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1712
1713         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1714                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1715         else
1716                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1717
1718         // free the strings
1719         if (vertstring)
1720                 Mem_Free(vertstring);
1721         if (geomstring)
1722                 Mem_Free(geomstring);
1723         if (fragstring)
1724                 Mem_Free(fragstring);
1725         if (vertexstring)
1726                 Mem_Free(vertexstring);
1727         if (geometrystring)
1728                 Mem_Free(geometrystring);
1729         if (fragmentstring)
1730                 Mem_Free(fragmentstring);
1731 }
1732
1733 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1739
1740 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1741 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1742 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);}
1743 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);}
1744 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);}
1745 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);}
1746
1747 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1748 {
1749         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1750         if (r_hlsl_permutation != perm)
1751         {
1752                 r_hlsl_permutation = perm;
1753                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1754                 {
1755                         if (!r_hlsl_permutation->compiled)
1756                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1757                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                         {
1759                                 // remove features until we find a valid permutation
1760                                 int i;
1761                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1762                                 {
1763                                         // reduce i more quickly whenever it would not remove any bits
1764                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1765                                         if (!(permutation & j))
1766                                                 continue;
1767                                         permutation -= j;
1768                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1769                                         if (!r_hlsl_permutation->compiled)
1770                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1771                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772                                                 break;
1773                                 }
1774                                 if (i >= SHADERPERMUTATION_COUNT)
1775                                 {
1776                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1777                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1778                                         return; // no bit left to clear, entire mode is broken
1779                                 }
1780                         }
1781                 }
1782                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1783                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1784         }
1785         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1786         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1787         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1788 }
1789 #endif
1790
1791 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1792 {
1793         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1794         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1795         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1796         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 }
1798
1799 void R_GLSL_Restart_f(void)
1800 {
1801         unsigned int i, limit;
1802         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1803                 Mem_Free(glslshaderstring);
1804         glslshaderstring = NULL;
1805         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1806                 Mem_Free(hlslshaderstring);
1807         hlslshaderstring = NULL;
1808         switch(vid.renderpath)
1809         {
1810         case RENDERPATH_D3D9:
1811 #ifdef SUPPORTD3D
1812                 {
1813                         r_hlsl_permutation_t *p;
1814                         r_hlsl_permutation = NULL;
1815                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1816                         for (i = 0;i < limit;i++)
1817                         {
1818                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1819                                 {
1820                                         if (p->vertexshader)
1821                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1822                                         if (p->pixelshader)
1823                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1824                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825                                 }
1826                         }
1827                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1828                 }
1829 #endif
1830                 break;
1831         case RENDERPATH_D3D10:
1832                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1833                 break;
1834         case RENDERPATH_D3D11:
1835                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836                 break;
1837         case RENDERPATH_GL20:
1838         case RENDERPATH_GLES2:
1839                 {
1840                         r_glsl_permutation_t *p;
1841                         r_glsl_permutation = NULL;
1842                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1843                         for (i = 0;i < limit;i++)
1844                         {
1845                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1846                                 {
1847                                         GL_Backend_FreeProgram(p->program);
1848                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849                                 }
1850                         }
1851                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852                 }
1853                 break;
1854         case RENDERPATH_GL11:
1855         case RENDERPATH_GL13:
1856         case RENDERPATH_GLES1:
1857                 break;
1858         case RENDERPATH_SOFT:
1859                 break;
1860         }
1861 }
1862
1863 void R_GLSL_DumpShader_f(void)
1864 {
1865         int i;
1866         qfile_t *file;
1867
1868         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1869         if (file)
1870         {
1871                 FS_Print(file, "/* The engine may define the following macros:\n");
1872                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1873                 for (i = 0;i < SHADERMODE_COUNT;i++)
1874                         FS_Print(file, glslshadermodeinfo[i].pretext);
1875                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876                         FS_Print(file, shaderpermutationinfo[i].pretext);
1877                 FS_Print(file, "*/\n");
1878                 FS_Print(file, builtinshaderstring);
1879                 FS_Close(file);
1880                 Con_Printf("glsl/default.glsl written\n");
1881         }
1882         else
1883                 Con_Printf("failed to write to glsl/default.glsl\n");
1884
1885         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1886         if (file)
1887         {
1888                 FS_Print(file, "/* The engine may define the following macros:\n");
1889                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1890                 for (i = 0;i < SHADERMODE_COUNT;i++)
1891                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1892                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1893                         FS_Print(file, shaderpermutationinfo[i].pretext);
1894                 FS_Print(file, "*/\n");
1895                 FS_Print(file, builtinhlslshaderstring);
1896                 FS_Close(file);
1897                 Con_Printf("hlsl/default.hlsl written\n");
1898         }
1899         else
1900                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1901 }
1902
1903 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1904 {
1905         if (!second)
1906                 texturemode = GL_MODULATE;
1907         switch (vid.renderpath)
1908         {
1909         case RENDERPATH_D3D9:
1910 #ifdef SUPPORTD3D
1911                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1912                 R_Mesh_TexBind(GL20TU_FIRST , first );
1913                 R_Mesh_TexBind(GL20TU_SECOND, second);
1914 #endif
1915                 break;
1916         case RENDERPATH_D3D10:
1917                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1918                 break;
1919         case RENDERPATH_D3D11:
1920                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1921                 break;
1922         case RENDERPATH_GL20:
1923         case RENDERPATH_GLES2:
1924                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1925                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1926                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1927                 break;
1928         case RENDERPATH_GL13:
1929         case RENDERPATH_GLES1:
1930                 R_Mesh_TexBind(0, first );
1931                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1932                 R_Mesh_TexBind(1, second);
1933                 if (second)
1934                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1935                 break;
1936         case RENDERPATH_GL11:
1937                 R_Mesh_TexBind(0, first );
1938                 break;
1939         case RENDERPATH_SOFT:
1940                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1941                 R_Mesh_TexBind(GL20TU_FIRST , first );
1942                 R_Mesh_TexBind(GL20TU_SECOND, second);
1943                 break;
1944         }
1945 }
1946
1947 void R_SetupShader_DepthOrShadow(void)
1948 {
1949         switch (vid.renderpath)
1950         {
1951         case RENDERPATH_D3D9:
1952 #ifdef SUPPORTD3D
1953                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1954 #endif
1955                 break;
1956         case RENDERPATH_D3D10:
1957                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_D3D11:
1960                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961                 break;
1962         case RENDERPATH_GL20:
1963         case RENDERPATH_GLES2:
1964                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1965                 break;
1966         case RENDERPATH_GL13:
1967         case RENDERPATH_GLES1:
1968                 R_Mesh_TexBind(0, 0);
1969                 R_Mesh_TexBind(1, 0);
1970                 break;
1971         case RENDERPATH_GL11:
1972                 R_Mesh_TexBind(0, 0);
1973                 break;
1974         case RENDERPATH_SOFT:
1975                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1976                 break;
1977         }
1978 }
1979
1980 void R_SetupShader_ShowDepth(void)
1981 {
1982         switch (vid.renderpath)
1983         {
1984         case RENDERPATH_D3D9:
1985 #ifdef SUPPORTHLSL
1986                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1987 #endif
1988                 break;
1989         case RENDERPATH_D3D10:
1990                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991                 break;
1992         case RENDERPATH_D3D11:
1993                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994                 break;
1995         case RENDERPATH_GL20:
1996         case RENDERPATH_GLES2:
1997                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1998                 break;
1999         case RENDERPATH_GL13:
2000         case RENDERPATH_GLES1:
2001                 break;
2002         case RENDERPATH_GL11:
2003                 break;
2004         case RENDERPATH_SOFT:
2005                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2006                 break;
2007         }
2008 }
2009
2010 extern qboolean r_shadow_usingdeferredprepass;
2011 extern cvar_t r_shadow_deferred_8bitrange;
2012 extern rtexture_t *r_shadow_attenuationgradienttexture;
2013 extern rtexture_t *r_shadow_attenuation2dtexture;
2014 extern rtexture_t *r_shadow_attenuation3dtexture;
2015 extern qboolean r_shadow_usingshadowmap2d;
2016 extern qboolean r_shadow_usingshadowmaportho;
2017 extern float r_shadow_shadowmap_texturescale[2];
2018 extern float r_shadow_shadowmap_parameters[4];
2019 extern qboolean r_shadow_shadowmapvsdct;
2020 extern qboolean r_shadow_shadowmapsampler;
2021 extern int r_shadow_shadowmappcf;
2022 extern rtexture_t *r_shadow_shadowmap2dtexture;
2023 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2024 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2025 extern matrix4x4_t r_shadow_shadowmapmatrix;
2026 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2027 extern int r_shadow_prepass_width;
2028 extern int r_shadow_prepass_height;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2030 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2031 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2032 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2033 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2034
2035 #define BLENDFUNC_ALLOWS_COLORMOD      1
2036 #define BLENDFUNC_ALLOWS_FOG           2
2037 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2038 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2039 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2040 static int R_BlendFuncFlags(int src, int dst)
2041 {
2042         int r = 0;
2043
2044         // a blendfunc allows colormod if:
2045         // a) it can never keep the destination pixel invariant, or
2046         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2047         // this is to prevent unintended side effects from colormod
2048
2049         // a blendfunc allows fog if:
2050         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2051         // this is to prevent unintended side effects from fog
2052
2053         // these checks are the output of fogeval.pl
2054
2055         r |= BLENDFUNC_ALLOWS_COLORMOD;
2056         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2057         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2058         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2060         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2063         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2064         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2065         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2071         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2073         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2076         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2077
2078         return r;
2079 }
2080
2081 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)
2082 {
2083         // select a permutation of the lighting shader appropriate to this
2084         // combination of texture, entity, light source, and fogging, only use the
2085         // minimum features necessary to avoid wasting rendering time in the
2086         // fragment shader on features that are not being used
2087         unsigned int permutation = 0;
2088         unsigned int mode = 0;
2089         int blendfuncflags;
2090         static float dummy_colormod[3] = {1, 1, 1};
2091         float *colormod = rsurface.colormod;
2092         float m16f[16];
2093         matrix4x4_t tempmatrix;
2094         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2095         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2096                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2097         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2098                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2099         if (rsurfacepass == RSURFPASS_BACKGROUND)
2100         {
2101                 // distorted background
2102                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2103                 {
2104                         mode = SHADERMODE_WATER;
2105                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2106                         {
2107                                 // this is the right thing to do for wateralpha
2108                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2109                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2110                         }
2111                         else
2112                         {
2113                                 // this is the right thing to do for entity alpha
2114                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116                         }
2117                 }
2118                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2119                 {
2120                         mode = SHADERMODE_REFRACTION;
2121                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2123                 }
2124                 else
2125                 {
2126                         mode = SHADERMODE_GENERIC;
2127                         permutation |= SHADERPERMUTATION_DIFFUSE;
2128                         GL_BlendFunc(GL_ONE, GL_ZERO);
2129                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2130                 }
2131         }
2132         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2133         {
2134                 if (r_glsl_offsetmapping.integer)
2135                 {
2136                         switch(rsurface.texture->offsetmapping)
2137                         {
2138                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2139                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2141                         case OFFSETMAPPING_OFF: break;
2142                         }
2143                 }
2144                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2145                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2146                 // normalmap (deferred prepass), may use alpha test on diffuse
2147                 mode = SHADERMODE_DEFERREDGEOMETRY;
2148                 GL_BlendFunc(GL_ONE, GL_ZERO);
2149                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2150         }
2151         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2152         {
2153                 if (r_glsl_offsetmapping.integer)
2154                 {
2155                         switch(rsurface.texture->offsetmapping)
2156                         {
2157                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2158                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2160                         case OFFSETMAPPING_OFF: break;
2161                         }
2162                 }
2163                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2164                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2165                 // light source
2166                 mode = SHADERMODE_LIGHTSOURCE;
2167                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2168                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2169                 if (diffusescale > 0)
2170                         permutation |= SHADERPERMUTATION_DIFFUSE;
2171                 if (specularscale > 0)
2172                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2173                 if (r_refdef.fogenabled)
2174                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2175                 if (rsurface.texture->colormapping)
2176                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2177                 if (r_shadow_usingshadowmap2d)
2178                 {
2179                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2180                         if(r_shadow_shadowmapvsdct)
2181                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2182
2183                         if (r_shadow_shadowmapsampler)
2184                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2185                         if (r_shadow_shadowmappcf > 1)
2186                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2187                         else if (r_shadow_shadowmappcf)
2188                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2189                 }
2190                 if (rsurface.texture->reflectmasktexture)
2191                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2192                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2193                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2194         }
2195         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2196         {
2197                 if (r_glsl_offsetmapping.integer)
2198                 {
2199                         switch(rsurface.texture->offsetmapping)
2200                         {
2201                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2202                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2204                         case OFFSETMAPPING_OFF: break;
2205                         }
2206                 }
2207                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2208                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2209                 // unshaded geometry (fullbright or ambient model lighting)
2210                 mode = SHADERMODE_FLATCOLOR;
2211                 ambientscale = diffusescale = specularscale = 0;
2212                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2213                         permutation |= SHADERPERMUTATION_GLOW;
2214                 if (r_refdef.fogenabled)
2215                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2216                 if (rsurface.texture->colormapping)
2217                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2218                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2219                 {
2220                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2221                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222
2223                         if (r_shadow_shadowmapsampler)
2224                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2225                         if (r_shadow_shadowmappcf > 1)
2226                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2227                         else if (r_shadow_shadowmappcf)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2229                 }
2230                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2231                         permutation |= SHADERPERMUTATION_REFLECTION;
2232                 if (rsurface.texture->reflectmasktexture)
2233                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2236         }
2237         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2238         {
2239                 if (r_glsl_offsetmapping.integer)
2240                 {
2241                         switch(rsurface.texture->offsetmapping)
2242                         {
2243                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2244                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2246                         case OFFSETMAPPING_OFF: break;
2247                         }
2248                 }
2249                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2250                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2251                 // directional model lighting
2252                 mode = SHADERMODE_LIGHTDIRECTION;
2253                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2254                         permutation |= SHADERPERMUTATION_GLOW;
2255                 permutation |= SHADERPERMUTATION_DIFFUSE;
2256                 if (specularscale > 0)
2257                         permutation |= SHADERPERMUTATION_SPECULAR;
2258                 if (r_refdef.fogenabled)
2259                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260                 if (rsurface.texture->colormapping)
2261                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2262                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2263                 {
2264                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2266
2267                         if (r_shadow_shadowmapsampler)
2268                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269                         if (r_shadow_shadowmappcf > 1)
2270                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271                         else if (r_shadow_shadowmappcf)
2272                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2273                 }
2274                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275                         permutation |= SHADERPERMUTATION_REFLECTION;
2276                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2277                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2278                 if (rsurface.texture->reflectmasktexture)
2279                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2280                 if (r_shadow_bouncegridtexture)
2281                 {
2282                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2283                         if (r_shadow_bouncegriddirectional)
2284                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2285                 }
2286                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2288         }
2289         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2290         {
2291                 if (r_glsl_offsetmapping.integer)
2292                 {
2293                         switch(rsurface.texture->offsetmapping)
2294                         {
2295                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2296                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2298                         case OFFSETMAPPING_OFF: break;
2299                         }
2300                 }
2301                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303                 // ambient model lighting
2304                 mode = SHADERMODE_LIGHTDIRECTION;
2305                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2306                         permutation |= SHADERPERMUTATION_GLOW;
2307                 if (r_refdef.fogenabled)
2308                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309                 if (rsurface.texture->colormapping)
2310                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2311                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2312                 {
2313                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2314                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2315
2316                         if (r_shadow_shadowmapsampler)
2317                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2318                         if (r_shadow_shadowmappcf > 1)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2320                         else if (r_shadow_shadowmappcf)
2321                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2324                         permutation |= SHADERPERMUTATION_REFLECTION;
2325                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2326                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2327                 if (rsurface.texture->reflectmasktexture)
2328                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2329                 if (r_shadow_bouncegridtexture)
2330                 {
2331                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2332                         if (r_shadow_bouncegriddirectional)
2333                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334                 }
2335                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337         }
2338         else
2339         {
2340                 if (r_glsl_offsetmapping.integer)
2341                 {
2342                         switch(rsurface.texture->offsetmapping)
2343                         {
2344                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2345                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347                         case OFFSETMAPPING_OFF: break;
2348                         }
2349                 }
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2351                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2352                 // lightmapped wall
2353                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2354                         permutation |= SHADERPERMUTATION_GLOW;
2355                 if (r_refdef.fogenabled)
2356                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2357                 if (rsurface.texture->colormapping)
2358                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2359                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2360                 {
2361                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2362                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2363
2364                         if (r_shadow_shadowmapsampler)
2365                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2366                         if (r_shadow_shadowmappcf > 1)
2367                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2368                         else if (r_shadow_shadowmappcf)
2369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2370                 }
2371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2372                         permutation |= SHADERPERMUTATION_REFLECTION;
2373                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2374                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2375                 if (rsurface.texture->reflectmasktexture)
2376                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2377                 if (FAKELIGHT_ENABLED)
2378                 {
2379                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2380                         mode = SHADERMODE_FAKELIGHT;
2381                         permutation |= SHADERPERMUTATION_DIFFUSE;
2382                         if (specularscale > 0)
2383                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2384                 }
2385                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2386                 {
2387                         // deluxemapping (light direction texture)
2388                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2389                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2390                         else
2391                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392                         permutation |= SHADERPERMUTATION_DIFFUSE;
2393                         if (specularscale > 0)
2394                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395                 }
2396                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2397                 {
2398                         // fake deluxemapping (uniform light direction in tangentspace)
2399                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2400                         permutation |= SHADERPERMUTATION_DIFFUSE;
2401                         if (specularscale > 0)
2402                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2403                 }
2404                 else if (rsurface.uselightmaptexture)
2405                 {
2406                         // ordinary lightmapping (q1bsp, q3bsp)
2407                         mode = SHADERMODE_LIGHTMAP;
2408                 }
2409                 else
2410                 {
2411                         // ordinary vertex coloring (q3bsp)
2412                         mode = SHADERMODE_VERTEXCOLOR;
2413                 }
2414                 if (r_shadow_bouncegridtexture)
2415                 {
2416                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417                         if (r_shadow_bouncegriddirectional)
2418                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419                 }
2420                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422         }
2423         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2424                 colormod = dummy_colormod;
2425         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2426                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2427         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2428                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2429         switch(vid.renderpath)
2430         {
2431         case RENDERPATH_D3D9:
2432 #ifdef SUPPORTD3D
2433                 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);
2434                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2435                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2436                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2437                 if (mode == SHADERMODE_LIGHTSOURCE)
2438                 {
2439                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2440                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2441                 }
2442                 else
2443                 {
2444                         if (mode == SHADERMODE_LIGHTDIRECTION)
2445                         {
2446                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447                         }
2448                 }
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2451                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2452                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2453                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2454
2455                 if (mode == SHADERMODE_LIGHTSOURCE)
2456                 {
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2461                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2462
2463                         // additive passes are only darkened by fog, not tinted
2464                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2465                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2466                 }
2467                 else
2468                 {
2469                         if (mode == SHADERMODE_FLATCOLOR)
2470                         {
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2472                         }
2473                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2474                         {
2475                                 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]);
2476                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2477                                 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);
2478                                 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);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2482                         }
2483                         else
2484                         {
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2486                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2487                                 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);
2488                                 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);
2489                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2490                         }
2491                         // additive passes are only darkened by fog, not tinted
2492                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2493                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2494                         else
2495                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2496                         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);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2503                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2504                         if (mode == SHADERMODE_WATER)
2505                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2506                 }
2507                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2508                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2509                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2510                 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));
2511                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2512                 if (rsurface.texture->pantstexture)
2513                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2514                 else
2515                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2516                 if (rsurface.texture->shirttexture)
2517                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2518                 else
2519                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2520                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2523                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2524                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2525                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2526                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2528                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2529                         );
2530                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2531                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2532
2533                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2534                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2535                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2536                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2538                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2539                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2540                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2541                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2542                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2543                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2544                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2545                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2546                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2547                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2548                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2549                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2550                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2551                 {
2552                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2553                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2554                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2555                 }
2556                 else
2557                 {
2558                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2559                 }
2560 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2561 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2562                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2563                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2564                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2565                 {
2566                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2567                         if (rsurface.rtlight)
2568                         {
2569                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2570                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2571                         }
2572                 }
2573 #endif
2574                 break;
2575         case RENDERPATH_D3D10:
2576                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2577                 break;
2578         case RENDERPATH_D3D11:
2579                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2580                 break;
2581         case RENDERPATH_GL20:
2582         case RENDERPATH_GLES2:
2583                 if (!vid.useinterleavedarrays)
2584                 {
2585                         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);
2586                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2587                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2591                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2592                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2593                 }
2594                 else
2595                 {
2596                         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);
2597                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2598                 }
2599                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2600                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2601                 if (mode == SHADERMODE_LIGHTSOURCE)
2602                 {
2603                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2604                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2605                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2606                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2607                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2608                         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);
2609         
2610                         // additive passes are only darkened by fog, not tinted
2611                         if (r_glsl_permutation->loc_FogColor >= 0)
2612                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2613                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2614                 }
2615                 else
2616                 {
2617                         if (mode == SHADERMODE_FLATCOLOR)
2618                         {
2619                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2620                         }
2621                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2622                         {
2623                                 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]);
2624                                 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]);
2625                                 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);
2626                                 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);
2627                                 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);
2628                                 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]);
2629                                 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]);
2630                         }
2631                         else
2632                         {
2633                                 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]);
2634                                 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]);
2635                                 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);
2636                                 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);
2637                                 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);
2638                         }
2639                         // additive passes are only darkened by fog, not tinted
2640                         if (r_glsl_permutation->loc_FogColor >= 0)
2641                         {
2642                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2643                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2644                                 else
2645                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2646                         }
2647                         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);
2648                         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]);
2649                         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]);
2650                         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]);
2651                         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]);
2652                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2653                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2654                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2655                         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]);
2656                 }
2657                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2658                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2659                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2660                 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]);
2661                 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]);
2662
2663                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2664                 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));
2665                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2666                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2667                 {
2668                         if (rsurface.texture->pantstexture)
2669                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2670                         else
2671                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2672                 }
2673                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2674                 {
2675                         if (rsurface.texture->shirttexture)
2676                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2677                         else
2678                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2679                 }
2680                 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]);
2681                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2682                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2683                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2684                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2685                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2686                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2688                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2689                         );
2690                 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]);
2691                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2692                 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);}
2693                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2694
2695                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2697                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2698                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2700                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2701                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2705                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2706                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2707                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2708                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2709                 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);
2710                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2711                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2712                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2715                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716                 {
2717                         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);
2718                         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);
2719                         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);
2720                 }
2721                 else
2722                 {
2723                         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);
2724                 }
2725                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2726                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2727                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2728                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2729                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730                 {
2731                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2732                         if (rsurface.rtlight)
2733                         {
2734                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2735                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2736                         }
2737                 }
2738                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739                 CHECKGLERROR
2740                 break;
2741         case RENDERPATH_GL11:
2742         case RENDERPATH_GL13:
2743         case RENDERPATH_GLES1:
2744                 break;
2745         case RENDERPATH_SOFT:
2746                 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);
2747                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2748                 R_SetupShader_SetPermutationSoft(mode, permutation);
2749                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2750                 if (mode == SHADERMODE_LIGHTSOURCE)
2751                 {
2752                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2757                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2758         
2759                         // additive passes are only darkened by fog, not tinted
2760                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2761                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2762                 }
2763                 else
2764                 {
2765                         if (mode == SHADERMODE_FLATCOLOR)
2766                         {
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2768                         }
2769                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2770                         {
2771                                 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]);
2772                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2773                                 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);
2774                                 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);
2775                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2776                                 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]);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2778                         }
2779                         else
2780                         {
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2782                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2783                                 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);
2784                                 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);
2785                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2786                         }
2787                         // additive passes are only darkened by fog, not tinted
2788                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2789                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2790                         else
2791                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2792                         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);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2794                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2795                         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]);
2796                         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]);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2799                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2800                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2801                 }
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2804                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2805                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2806                 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]);
2807
2808                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2809                 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));
2810                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2811                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2812                 {
2813                         if (rsurface.texture->pantstexture)
2814                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2815                         else
2816                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2817                 }
2818                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2819                 {
2820                         if (rsurface.texture->shirttexture)
2821                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2822                         else
2823                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2824                 }
2825                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2828                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2829                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2830                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2831                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2833                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2834                         );
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2836                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2837
2838                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2839                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2840                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2841                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2845                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2847                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2849                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2850                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2851                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2852                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2853                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2854                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2855                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2856                 {
2857                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2858                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2859                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860                 }
2861                 else
2862                 {
2863                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2864                 }
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2866 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2868                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2869                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2870                 {
2871                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2872                         if (rsurface.rtlight)
2873                         {
2874                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2875                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2876                         }
2877                 }
2878                 break;
2879         }
2880 }
2881
2882 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2883 {
2884         // select a permutation of the lighting shader appropriate to this
2885         // combination of texture, entity, light source, and fogging, only use the
2886         // minimum features necessary to avoid wasting rendering time in the
2887         // fragment shader on features that are not being used
2888         unsigned int permutation = 0;
2889         unsigned int mode = 0;
2890         const float *lightcolorbase = rtlight->currentcolor;
2891         float ambientscale = rtlight->ambientscale;
2892         float diffusescale = rtlight->diffusescale;
2893         float specularscale = rtlight->specularscale;
2894         // this is the location of the light in view space
2895         vec3_t viewlightorigin;
2896         // this transforms from view space (camera) to light space (cubemap)
2897         matrix4x4_t viewtolight;
2898         matrix4x4_t lighttoview;
2899         float viewtolight16f[16];
2900         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2901         // light source
2902         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2903         if (rtlight->currentcubemap != r_texture_whitecube)
2904                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2905         if (diffusescale > 0)
2906                 permutation |= SHADERPERMUTATION_DIFFUSE;
2907         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2908                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2909         if (r_shadow_usingshadowmap2d)
2910         {
2911                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2912                 if (r_shadow_shadowmapvsdct)
2913                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2914
2915                 if (r_shadow_shadowmapsampler)
2916                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2917                 if (r_shadow_shadowmappcf > 1)
2918                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2919                 else if (r_shadow_shadowmappcf)
2920                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2921         }
2922         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2923         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2924         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2925         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2926         switch(vid.renderpath)
2927         {
2928         case RENDERPATH_D3D9:
2929 #ifdef SUPPORTD3D
2930                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2931                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2932                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2935                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2936                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2937                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2938                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2939                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2940                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2941
2942                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2943                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2944                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2945                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2946                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2947                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2948 #endif
2949                 break;
2950         case RENDERPATH_D3D10:
2951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2952                 break;
2953         case RENDERPATH_D3D11:
2954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2955                 break;
2956         case RENDERPATH_GL20:
2957         case RENDERPATH_GLES2:
2958                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2961                 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);
2962                 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);
2963                 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);
2964                 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]);
2965                 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]);
2966                 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));
2967                 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]);
2968                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2969
2970                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2971                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2972                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2973                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2974                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2975                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2976                 break;
2977         case RENDERPATH_GL11:
2978         case RENDERPATH_GL13:
2979         case RENDERPATH_GLES1:
2980                 break;
2981         case RENDERPATH_SOFT:
2982                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2983                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2984                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2987                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2988                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2989                 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]);
2990                 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));
2991                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2992                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2993
2994                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2995                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2996                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2997                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2998                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2999                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3000                 break;
3001         }
3002 }
3003
3004 #define SKINFRAME_HASH 1024
3005
3006 typedef struct
3007 {
3008         int loadsequence; // incremented each level change
3009         memexpandablearray_t array;
3010         skinframe_t *hash[SKINFRAME_HASH];
3011 }
3012 r_skinframe_t;
3013 r_skinframe_t r_skinframe;
3014
3015 void R_SkinFrame_PrepareForPurge(void)
3016 {
3017         r_skinframe.loadsequence++;
3018         // wrap it without hitting zero
3019         if (r_skinframe.loadsequence >= 200)
3020                 r_skinframe.loadsequence = 1;
3021 }
3022
3023 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3024 {
3025         if (!skinframe)
3026                 return;
3027         // mark the skinframe as used for the purging code
3028         skinframe->loadsequence = r_skinframe.loadsequence;
3029 }
3030
3031 void R_SkinFrame_Purge(void)
3032 {
3033         int i;
3034         skinframe_t *s;
3035         for (i = 0;i < SKINFRAME_HASH;i++)
3036         {
3037                 for (s = r_skinframe.hash[i];s;s = s->next)
3038                 {
3039                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3040                         {
3041                                 if (s->merged == s->base)
3042                                         s->merged = NULL;
3043                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3044                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3045                                 R_PurgeTexture(s->merged);s->merged = NULL;
3046                                 R_PurgeTexture(s->base  );s->base   = NULL;
3047                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3048                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3049                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3050                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3051                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3052                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3053                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3054                                 s->loadsequence = 0;
3055                         }
3056                 }
3057         }
3058 }
3059
3060 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3061         skinframe_t *item;
3062         char basename[MAX_QPATH];
3063
3064         Image_StripImageExtension(name, basename, sizeof(basename));
3065
3066         if( last == NULL ) {
3067                 int hashindex;
3068                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3069                 item = r_skinframe.hash[hashindex];
3070         } else {
3071                 item = last->next;
3072         }
3073
3074         // linearly search through the hash bucket
3075         for( ; item ; item = item->next ) {
3076                 if( !strcmp( item->basename, basename ) ) {
3077                         return item;
3078                 }
3079         }
3080         return NULL;
3081 }
3082
3083 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3084 {
3085         skinframe_t *item;
3086         int hashindex;
3087         char basename[MAX_QPATH];
3088
3089         Image_StripImageExtension(name, basename, sizeof(basename));
3090
3091         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3092         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3093                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3094                         break;
3095
3096         if (!item) {
3097                 rtexture_t *dyntexture;
3098                 // check whether its a dynamic texture
3099                 dyntexture = CL_GetDynTexture( basename );
3100                 if (!add && !dyntexture)
3101                         return NULL;
3102                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3103                 memset(item, 0, sizeof(*item));
3104                 strlcpy(item->basename, basename, sizeof(item->basename));
3105                 item->base = dyntexture; // either NULL or dyntexture handle
3106                 item->textureflags = textureflags;
3107                 item->comparewidth = comparewidth;
3108                 item->compareheight = compareheight;
3109                 item->comparecrc = comparecrc;
3110                 item->next = r_skinframe.hash[hashindex];
3111                 r_skinframe.hash[hashindex] = item;
3112         }
3113         else if( item->base == NULL )
3114         {
3115                 rtexture_t *dyntexture;
3116                 // check whether its a dynamic texture
3117                 // 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]
3118                 dyntexture = CL_GetDynTexture( basename );
3119                 item->base = dyntexture; // either NULL or dyntexture handle
3120         }
3121
3122         R_SkinFrame_MarkUsed(item);
3123         return item;
3124 }
3125
3126 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3127         { \
3128                 unsigned long long avgcolor[5], wsum; \
3129                 int pix, comp, w; \
3130                 avgcolor[0] = 0; \
3131                 avgcolor[1] = 0; \
3132                 avgcolor[2] = 0; \
3133                 avgcolor[3] = 0; \
3134                 avgcolor[4] = 0; \
3135                 wsum = 0; \
3136                 for(pix = 0; pix < cnt; ++pix) \
3137                 { \
3138                         w = 0; \
3139                         for(comp = 0; comp < 3; ++comp) \
3140                                 w += getpixel; \
3141                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3142                         { \
3143                                 ++wsum; \
3144                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3145                                 w = getpixel; \
3146                                 for(comp = 0; comp < 3; ++comp) \
3147                                         avgcolor[comp] += getpixel * w; \
3148                                 avgcolor[3] += w; \
3149                         } \
3150                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3151                         avgcolor[4] += getpixel; \
3152                 } \
3153                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3154                         avgcolor[3] = 1; \
3155                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3158                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3159         }
3160
3161 extern cvar_t gl_picmip;
3162 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3163 {
3164         int j;
3165         unsigned char *pixels;
3166         unsigned char *bumppixels;
3167         unsigned char *basepixels = NULL;
3168         int basepixels_width = 0;
3169         int basepixels_height = 0;
3170         skinframe_t *skinframe;
3171         rtexture_t *ddsbase = NULL;
3172         qboolean ddshasalpha = false;
3173         float ddsavgcolor[4];
3174         char basename[MAX_QPATH];
3175         int miplevel = R_PicmipForFlags(textureflags);
3176         int savemiplevel = miplevel;
3177         int mymiplevel;
3178
3179         if (cls.state == ca_dedicated)
3180                 return NULL;
3181
3182         // return an existing skinframe if already loaded
3183         // if loading of the first image fails, don't make a new skinframe as it
3184         // would cause all future lookups of this to be missing
3185         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3186         if (skinframe && skinframe->base)
3187                 return skinframe;
3188
3189         Image_StripImageExtension(name, basename, sizeof(basename));
3190
3191         // check for DDS texture file first
3192         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3193         {
3194                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3195                 if (basepixels == NULL)
3196                         return NULL;
3197         }
3198
3199         // FIXME handle miplevel
3200
3201         if (developer_loading.integer)
3202                 Con_Printf("loading skin \"%s\"\n", name);
3203
3204         // we've got some pixels to store, so really allocate this new texture now
3205         if (!skinframe)
3206                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3207         skinframe->stain = NULL;
3208         skinframe->merged = NULL;
3209         skinframe->base = NULL;
3210         skinframe->pants = NULL;
3211         skinframe->shirt = NULL;
3212         skinframe->nmap = NULL;
3213         skinframe->gloss = NULL;
3214         skinframe->glow = NULL;
3215         skinframe->fog = NULL;
3216         skinframe->reflect = NULL;
3217         skinframe->hasalpha = false;
3218
3219         if (ddsbase)
3220         {
3221                 skinframe->base = ddsbase;
3222                 skinframe->hasalpha = ddshasalpha;
3223                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3224                 if (r_loadfog && skinframe->hasalpha)
3225                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3226                 //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]);
3227         }
3228         else
3229         {
3230                 basepixels_width = image_width;
3231                 basepixels_height = image_height;
3232                 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);
3233                 if (textureflags & TEXF_ALPHA)
3234                 {
3235                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3236                         {
3237                                 if (basepixels[j] < 255)
3238                                 {
3239                                         skinframe->hasalpha = true;
3240                                         break;
3241                                 }
3242                         }
3243                         if (r_loadfog && skinframe->hasalpha)
3244                         {
3245                                 // has transparent pixels
3246                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3247                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3248                                 {
3249                                         pixels[j+0] = 255;
3250                                         pixels[j+1] = 255;
3251                                         pixels[j+2] = 255;
3252                                         pixels[j+3] = basepixels[j+3];
3253                                 }
3254                                 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);
3255                                 Mem_Free(pixels);
3256                         }
3257                 }
3258                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3259                 //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]);
3260                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3261                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3262                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3263                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3264         }
3265
3266         if (r_loaddds)
3267         {
3268                 mymiplevel = savemiplevel;
3269                 if (r_loadnormalmap)
3270                         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);
3271                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272                 if (r_loadgloss)
3273                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3277         }
3278
3279         // _norm is the name used by tenebrae and has been adopted as standard
3280         if (r_loadnormalmap && skinframe->nmap == NULL)
3281         {
3282                 mymiplevel = savemiplevel;
3283                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3284                 {
3285                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3286                         Mem_Free(pixels);
3287                         pixels = NULL;
3288                 }
3289                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3290                 {
3291                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3292                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3293                         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);
3294                         Mem_Free(pixels);
3295                         Mem_Free(bumppixels);
3296                 }
3297                 else if (r_shadow_bumpscale_basetexture.value > 0)
3298                 {
3299                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3300                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3301                         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);
3302                         Mem_Free(pixels);
3303                 }
3304                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3305                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3306         }
3307
3308         // _luma is supported only for tenebrae compatibility
3309         // _glow is the preferred name
3310         mymiplevel = savemiplevel;
3311         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))))
3312         {
3313                 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);
3314                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3315                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3316                 Mem_Free(pixels);pixels = NULL;
3317         }
3318
3319         mymiplevel = savemiplevel;
3320         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3321         {
3322                 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);
3323                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3324                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3325                 Mem_Free(pixels);
3326                 pixels = NULL;
3327         }
3328
3329         mymiplevel = savemiplevel;
3330         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3331         {
3332                 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);
3333                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3334                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3335                 Mem_Free(pixels);
3336                 pixels = NULL;
3337         }
3338
3339         mymiplevel = savemiplevel;
3340         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3341         {
3342                 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);
3343                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3344                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3345                 Mem_Free(pixels);
3346                 pixels = NULL;
3347         }
3348
3349         mymiplevel = savemiplevel;
3350         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3351         {
3352                 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);
3353                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3354                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3355                 Mem_Free(pixels);
3356                 pixels = NULL;
3357         }
3358
3359         if (basepixels)
3360                 Mem_Free(basepixels);
3361
3362         return skinframe;
3363 }
3364
3365 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3366 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3367 {
3368         int i;
3369         unsigned char *temp1, *temp2;
3370         skinframe_t *skinframe;
3371
3372         if (cls.state == ca_dedicated)
3373                 return NULL;
3374
3375         // if already loaded just return it, otherwise make a new skinframe
3376         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3377         if (skinframe && skinframe->base)
3378                 return skinframe;
3379
3380         skinframe->stain = NULL;
3381         skinframe->merged = NULL;
3382         skinframe->base = NULL;
3383         skinframe->pants = NULL;
3384         skinframe->shirt = NULL;
3385         skinframe->nmap = NULL;
3386         skinframe->gloss = NULL;
3387         skinframe->glow = NULL;
3388         skinframe->fog = NULL;
3389         skinframe->reflect = NULL;
3390         skinframe->hasalpha = false;
3391
3392         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3393         if (!skindata)
3394                 return NULL;
3395
3396         if (developer_loading.integer)
3397                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3398
3399         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3400         {
3401                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3402                 temp2 = temp1 + width * height * 4;
3403                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3404                 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);
3405                 Mem_Free(temp1);
3406         }
3407         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3408         if (textureflags & TEXF_ALPHA)
3409         {
3410                 for (i = 3;i < width * height * 4;i += 4)
3411                 {
3412                         if (skindata[i] < 255)
3413                         {
3414                                 skinframe->hasalpha = true;
3415                                 break;
3416                         }
3417                 }
3418                 if (r_loadfog && skinframe->hasalpha)
3419                 {
3420                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3421                         memcpy(fogpixels, skindata, width * height * 4);
3422                         for (i = 0;i < width * height * 4;i += 4)
3423                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3424                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3425                         Mem_Free(fogpixels);
3426                 }
3427         }
3428
3429         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3430         //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]);
3431
3432         return skinframe;
3433 }
3434
3435 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3436 {
3437         int i;
3438         int featuresmask;
3439         skinframe_t *skinframe;
3440
3441         if (cls.state == ca_dedicated)
3442                 return NULL;
3443
3444         // if already loaded just return it, otherwise make a new skinframe
3445         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3446         if (skinframe && skinframe->base)
3447                 return skinframe;
3448
3449         skinframe->stain = NULL;
3450         skinframe->merged = NULL;
3451         skinframe->base = NULL;
3452         skinframe->pants = NULL;
3453         skinframe->shirt = NULL;
3454         skinframe->nmap = NULL;
3455         skinframe->gloss = NULL;
3456         skinframe->glow = NULL;
3457         skinframe->fog = NULL;
3458         skinframe->reflect = NULL;
3459         skinframe->hasalpha = false;
3460
3461         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3462         if (!skindata)
3463                 return NULL;
3464
3465         if (developer_loading.integer)
3466                 Con_Printf("loading quake skin \"%s\"\n", name);
3467
3468         // 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)
3469         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3470         memcpy(skinframe->qpixels, skindata, width*height);
3471         skinframe->qwidth = width;
3472         skinframe->qheight = height;
3473
3474         featuresmask = 0;
3475         for (i = 0;i < width * height;i++)
3476                 featuresmask |= palette_featureflags[skindata[i]];
3477
3478         skinframe->hasalpha = false;
3479         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3480         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3481         skinframe->qgeneratemerged = true;
3482         skinframe->qgeneratebase = skinframe->qhascolormapping;
3483         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3484
3485         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3486         //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]);
3487
3488         return skinframe;
3489 }
3490
3491 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3492 {
3493         int width;
3494         int height;
3495         unsigned char *skindata;
3496
3497         if (!skinframe->qpixels)
3498                 return;
3499
3500         if (!skinframe->qhascolormapping)
3501                 colormapped = false;
3502
3503         if (colormapped)
3504         {
3505                 if (!skinframe->qgeneratebase)
3506                         return;
3507         }
3508         else
3509         {
3510                 if (!skinframe->qgeneratemerged)
3511                         return;
3512         }
3513
3514         width = skinframe->qwidth;
3515         height = skinframe->qheight;
3516         skindata = skinframe->qpixels;
3517
3518         if (skinframe->qgeneratenmap)
3519         {
3520                 unsigned char *temp1, *temp2;
3521                 skinframe->qgeneratenmap = false;
3522                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3523                 temp2 = temp1 + width * height * 4;
3524                 // use either a custom palette or the quake palette
3525                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3526                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3527                 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);
3528                 Mem_Free(temp1);
3529         }
3530
3531         if (skinframe->qgenerateglow)
3532         {
3533                 skinframe->qgenerateglow = false;
3534                 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
3535         }
3536
3537         if (colormapped)
3538         {
3539                 skinframe->qgeneratebase = false;
3540                 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);
3541                 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);
3542                 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);
3543         }
3544         else
3545         {
3546                 skinframe->qgeneratemerged = false;
3547                 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);
3548         }
3549
3550         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3551         {
3552                 Mem_Free(skinframe->qpixels);
3553                 skinframe->qpixels = NULL;
3554         }
3555 }
3556
3557 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)
3558 {
3559         int i;
3560         skinframe_t *skinframe;
3561
3562         if (cls.state == ca_dedicated)
3563                 return NULL;
3564
3565         // if already loaded just return it, otherwise make a new skinframe
3566         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3567         if (skinframe && skinframe->base)
3568                 return skinframe;
3569
3570         skinframe->stain = NULL;
3571         skinframe->merged = NULL;
3572         skinframe->base = NULL;
3573         skinframe->pants = NULL;
3574         skinframe->shirt = NULL;
3575         skinframe->nmap = NULL;
3576         skinframe->gloss = NULL;
3577         skinframe->glow = NULL;
3578         skinframe->fog = NULL;
3579         skinframe->reflect = NULL;
3580         skinframe->hasalpha = false;
3581
3582         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3583         if (!skindata)
3584                 return NULL;
3585
3586         if (developer_loading.integer)
3587                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3588
3589         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3590         if (textureflags & TEXF_ALPHA)
3591         {
3592                 for (i = 0;i < width * height;i++)
3593                 {
3594                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3595                         {
3596                                 skinframe->hasalpha = true;
3597                                 break;
3598                         }
3599                 }
3600                 if (r_loadfog && skinframe->hasalpha)
3601                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3602         }
3603
3604         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3605         //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]);
3606
3607         return skinframe;
3608 }
3609
3610 skinframe_t *R_SkinFrame_LoadMissing(void)
3611 {
3612         skinframe_t *skinframe;
3613
3614         if (cls.state == ca_dedicated)
3615                 return NULL;
3616
3617         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3618         skinframe->stain = NULL;
3619         skinframe->merged = NULL;
3620         skinframe->base = NULL;
3621         skinframe->pants = NULL;
3622         skinframe->shirt = NULL;
3623         skinframe->nmap = NULL;
3624         skinframe->gloss = NULL;
3625         skinframe->glow = NULL;
3626         skinframe->fog = NULL;
3627         skinframe->reflect = NULL;
3628         skinframe->hasalpha = false;
3629
3630         skinframe->avgcolor[0] = rand() / RAND_MAX;
3631         skinframe->avgcolor[1] = rand() / RAND_MAX;
3632         skinframe->avgcolor[2] = rand() / RAND_MAX;
3633         skinframe->avgcolor[3] = 1;
3634
3635         return skinframe;
3636 }
3637
3638 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3639 typedef struct suffixinfo_s
3640 {
3641         const char *suffix;
3642         qboolean flipx, flipy, flipdiagonal;
3643 }
3644 suffixinfo_t;
3645 static suffixinfo_t suffix[3][6] =
3646 {
3647         {
3648                 {"px",   false, false, false},
3649                 {"nx",   false, false, false},
3650                 {"py",   false, false, false},
3651                 {"ny",   false, false, false},
3652                 {"pz",   false, false, false},
3653                 {"nz",   false, false, false}
3654         },
3655         {
3656                 {"posx", false, false, false},
3657                 {"negx", false, false, false},
3658                 {"posy", false, false, false},
3659                 {"negy", false, false, false},
3660                 {"posz", false, false, false},
3661                 {"negz", false, false, false}
3662         },
3663         {
3664                 {"rt",    true, false,  true},
3665                 {"lf",   false,  true,  true},
3666                 {"ft",    true,  true, false},
3667                 {"bk",   false, false, false},
3668                 {"up",    true, false,  true},
3669                 {"dn",    true, false,  true}
3670         }
3671 };
3672
3673 static int componentorder[4] = {0, 1, 2, 3};
3674
3675 rtexture_t *R_LoadCubemap(const char *basename)
3676 {
3677         int i, j, cubemapsize;
3678         unsigned char *cubemappixels, *image_buffer;
3679         rtexture_t *cubemaptexture;
3680         char name[256];
3681         // must start 0 so the first loadimagepixels has no requested width/height
3682         cubemapsize = 0;
3683         cubemappixels = NULL;
3684         cubemaptexture = NULL;
3685         // keep trying different suffix groups (posx, px, rt) until one loads
3686         for (j = 0;j < 3 && !cubemappixels;j++)
3687         {
3688                 // load the 6 images in the suffix group
3689                 for (i = 0;i < 6;i++)
3690                 {
3691                         // generate an image name based on the base and and suffix
3692                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3693                         // load it
3694                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3695                         {
3696                                 // an image loaded, make sure width and height are equal
3697                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3698                                 {
3699                                         // if this is the first image to load successfully, allocate the cubemap memory
3700                                         if (!cubemappixels && image_width >= 1)
3701                                         {
3702                                                 cubemapsize = image_width;
3703                                                 // note this clears to black, so unavailable sides are black
3704                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3705                                         }
3706                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3707                                         if (cubemappixels)
3708                                                 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);
3709                                 }
3710                                 else
3711                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3712                                 // free the image
3713                                 Mem_Free(image_buffer);
3714                         }
3715                 }
3716         }
3717         // if a cubemap loaded, upload it
3718         if (cubemappixels)
3719         {
3720                 if (developer_loading.integer)
3721                         Con_Printf("loading cubemap \"%s\"\n", basename);
3722
3723                 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);
3724                 Mem_Free(cubemappixels);
3725         }
3726         else
3727         {
3728                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3729                 if (developer_loading.integer)
3730                 {
3731                         Con_Printf("(tried tried images ");
3732                         for (j = 0;j < 3;j++)
3733                                 for (i = 0;i < 6;i++)
3734                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3735                         Con_Print(" and was unable to find any of them).\n");
3736                 }
3737         }
3738         return cubemaptexture;
3739 }
3740
3741 rtexture_t *R_GetCubemap(const char *basename)
3742 {
3743         int i;
3744         for (i = 0;i < r_texture_numcubemaps;i++)
3745                 if (r_texture_cubemaps[i] != NULL)
3746                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3747                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3748         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3749                 return r_texture_whitecube;
3750         r_texture_numcubemaps++;
3751         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3752         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3753         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3754         return r_texture_cubemaps[i]->texture;
3755 }
3756
3757 void R_FreeCubemap(const char *basename)
3758 {
3759         int i;
3760
3761         for (i = 0;i < r_texture_numcubemaps;i++)
3762         {
3763                 if (r_texture_cubemaps[i] != NULL)
3764                 {
3765                         if (r_texture_cubemaps[i]->texture)
3766                         {
3767                                 if (developer_loading.integer)
3768                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3769                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3770                                 Mem_Free(r_texture_cubemaps[i]);
3771                                 r_texture_cubemaps[i] = NULL;
3772                         }
3773                 }
3774         }
3775 }
3776
3777 void R_FreeCubemaps(void)
3778 {
3779         int i;
3780         for (i = 0;i < r_texture_numcubemaps;i++)
3781         {
3782                 if (developer_loading.integer)
3783                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3784                 if (r_texture_cubemaps[i] != NULL)
3785                 {
3786                         if (r_texture_cubemaps[i]->texture)
3787                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3788                         Mem_Free(r_texture_cubemaps[i]);
3789                 }
3790         }
3791         r_texture_numcubemaps = 0;
3792 }
3793
3794 void R_Main_FreeViewCache(void)
3795 {
3796         if (r_refdef.viewcache.entityvisible)
3797                 Mem_Free(r_refdef.viewcache.entityvisible);
3798         if (r_refdef.viewcache.world_pvsbits)
3799                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3800         if (r_refdef.viewcache.world_leafvisible)
3801                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3802         if (r_refdef.viewcache.world_surfacevisible)
3803                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3804         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3805 }
3806
3807 void R_Main_ResizeViewCache(void)
3808 {
3809         int numentities = r_refdef.scene.numentities;
3810         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3811         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3812         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3813         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3814         if (r_refdef.viewcache.maxentities < numentities)
3815         {
3816                 r_refdef.viewcache.maxentities = numentities;
3817                 if (r_refdef.viewcache.entityvisible)
3818                         Mem_Free(r_refdef.viewcache.entityvisible);
3819                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3820         }
3821         if (r_refdef.viewcache.world_numclusters != numclusters)
3822         {
3823                 r_refdef.viewcache.world_numclusters = numclusters;
3824                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3825                 if (r_refdef.viewcache.world_pvsbits)
3826                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3827                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3828         }
3829         if (r_refdef.viewcache.world_numleafs != numleafs)
3830         {
3831                 r_refdef.viewcache.world_numleafs = numleafs;
3832                 if (r_refdef.viewcache.world_leafvisible)
3833                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3834                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3835         }
3836         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3837         {
3838                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3839                 if (r_refdef.viewcache.world_surfacevisible)
3840                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3841                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3842         }
3843 }
3844
3845 extern rtexture_t *loadingscreentexture;
3846 void gl_main_start(void)
3847 {
3848         loadingscreentexture = NULL;
3849         r_texture_blanknormalmap = NULL;
3850         r_texture_white = NULL;
3851         r_texture_grey128 = NULL;
3852         r_texture_black = NULL;
3853         r_texture_whitecube = NULL;
3854         r_texture_normalizationcube = NULL;
3855         r_texture_fogattenuation = NULL;
3856         r_texture_fogheighttexture = NULL;
3857         r_texture_gammaramps = NULL;
3858         r_texture_numcubemaps = 0;
3859
3860         r_loaddds = r_texture_dds_load.integer != 0;
3861         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3862
3863         switch(vid.renderpath)
3864         {
3865         case RENDERPATH_GL20:
3866         case RENDERPATH_D3D9:
3867         case RENDERPATH_D3D10:
3868         case RENDERPATH_D3D11:
3869         case RENDERPATH_SOFT:
3870         case RENDERPATH_GLES2:
3871                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3872                 Cvar_SetValueQuick(&gl_combine, 1);
3873                 Cvar_SetValueQuick(&r_glsl, 1);
3874                 r_loadnormalmap = true;
3875                 r_loadgloss = true;
3876                 r_loadfog = false;
3877                 break;
3878         case RENDERPATH_GL13:
3879         case RENDERPATH_GLES1:
3880                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3881                 Cvar_SetValueQuick(&gl_combine, 1);
3882                 Cvar_SetValueQuick(&r_glsl, 0);
3883                 r_loadnormalmap = false;
3884                 r_loadgloss = false;
3885                 r_loadfog = true;
3886                 break;
3887         case RENDERPATH_GL11:
3888                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3889                 Cvar_SetValueQuick(&gl_combine, 0);
3890                 Cvar_SetValueQuick(&r_glsl, 0);
3891                 r_loadnormalmap = false;
3892                 r_loadgloss = false;
3893                 r_loadfog = true;
3894                 break;
3895         }
3896
3897         R_AnimCache_Free();
3898         R_FrameData_Reset();
3899
3900         r_numqueries = 0;
3901         r_maxqueries = 0;
3902         memset(r_queries, 0, sizeof(r_queries));
3903
3904         r_qwskincache = NULL;
3905         r_qwskincache_size = 0;
3906
3907         // due to caching of texture_t references, the collision cache must be reset
3908         Collision_Cache_Reset(true);
3909
3910         // set up r_skinframe loading system for textures
3911         memset(&r_skinframe, 0, sizeof(r_skinframe));
3912         r_skinframe.loadsequence = 1;
3913         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3914
3915         r_main_texturepool = R_AllocTexturePool();
3916         R_BuildBlankTextures();
3917         R_BuildNoTexture();
3918         if (vid.support.arb_texture_cube_map)
3919         {
3920                 R_BuildWhiteCube();
3921                 R_BuildNormalizationCube();
3922         }
3923         r_texture_fogattenuation = NULL;
3924         r_texture_fogheighttexture = NULL;
3925         r_texture_gammaramps = NULL;
3926         //r_texture_fogintensity = NULL;
3927         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3928         memset(&r_waterstate, 0, sizeof(r_waterstate));
3929         r_glsl_permutation = NULL;
3930         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3931         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3932         glslshaderstring = NULL;
3933 #ifdef SUPPORTD3D
3934         r_hlsl_permutation = NULL;
3935         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3936         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3937 #endif
3938         hlslshaderstring = NULL;
3939         memset(&r_svbsp, 0, sizeof (r_svbsp));
3940
3941         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3942         r_texture_numcubemaps = 0;
3943
3944         r_refdef.fogmasktable_density = 0;
3945 }
3946
3947 void gl_main_shutdown(void)
3948 {
3949         R_AnimCache_Free();
3950         R_FrameData_Reset();
3951
3952         R_Main_FreeViewCache();
3953
3954         switch(vid.renderpath)
3955         {
3956         case RENDERPATH_GL11:
3957         case RENDERPATH_GL13:
3958         case RENDERPATH_GL20:
3959         case RENDERPATH_GLES1:
3960         case RENDERPATH_GLES2:
3961                 if (r_maxqueries)
3962                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3963                 break;
3964         case RENDERPATH_D3D9:
3965                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3966                 break;
3967         case RENDERPATH_D3D10:
3968                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3969                 break;
3970         case RENDERPATH_D3D11:
3971                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3972                 break;
3973         case RENDERPATH_SOFT:
3974                 break;
3975         }
3976
3977         r_numqueries = 0;
3978         r_maxqueries = 0;
3979         memset(r_queries, 0, sizeof(r_queries));
3980
3981         r_qwskincache = NULL;
3982         r_qwskincache_size = 0;
3983
3984         // clear out the r_skinframe state
3985         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3986         memset(&r_skinframe, 0, sizeof(r_skinframe));
3987
3988         if (r_svbsp.nodes)
3989                 Mem_Free(r_svbsp.nodes);
3990         memset(&r_svbsp, 0, sizeof (r_svbsp));
3991         R_FreeTexturePool(&r_main_texturepool);
3992         loadingscreentexture = NULL;
3993         r_texture_blanknormalmap = NULL;
3994         r_texture_white = NULL;
3995         r_texture_grey128 = NULL;
3996         r_texture_black = NULL;
3997         r_texture_whitecube = NULL;
3998         r_texture_normalizationcube = NULL;
3999         r_texture_fogattenuation = NULL;
4000         r_texture_fogheighttexture = NULL;
4001         r_texture_gammaramps = NULL;
4002         r_texture_numcubemaps = 0;
4003         //r_texture_fogintensity = NULL;
4004         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4005         memset(&r_waterstate, 0, sizeof(r_waterstate));
4006         R_GLSL_Restart_f();
4007
4008         r_glsl_permutation = NULL;
4009         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4010         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4011         glslshaderstring = NULL;
4012 #ifdef SUPPORTD3D
4013         r_hlsl_permutation = NULL;
4014         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4015         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4016 #endif
4017         hlslshaderstring = NULL;
4018 }
4019
4020 extern void CL_ParseEntityLump(char *entitystring);
4021 void gl_main_newmap(void)
4022 {
4023         // FIXME: move this code to client
4024         char *entities, entname[MAX_QPATH];
4025         if (r_qwskincache)
4026                 Mem_Free(r_qwskincache);
4027         r_qwskincache = NULL;
4028         r_qwskincache_size = 0;
4029         if (cl.worldmodel)
4030         {
4031                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4032                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4033                 {
4034                         CL_ParseEntityLump(entities);
4035                         Mem_Free(entities);
4036                         return;
4037                 }
4038                 if (cl.worldmodel->brush.entities)
4039                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4040         }
4041         R_Main_FreeViewCache();
4042
4043         R_FrameData_Reset();
4044 }
4045
4046 void GL_Main_Init(void)
4047 {
4048         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4049
4050         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4051         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4052         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4053         if (gamemode == GAME_NEHAHRA)
4054         {
4055                 Cvar_RegisterVariable (&gl_fogenable);
4056                 Cvar_RegisterVariable (&gl_fogdensity);
4057                 Cvar_RegisterVariable (&gl_fogred);
4058                 Cvar_RegisterVariable (&gl_foggreen);
4059                 Cvar_RegisterVariable (&gl_fogblue);
4060                 Cvar_RegisterVariable (&gl_fogstart);
4061                 Cvar_RegisterVariable (&gl_fogend);
4062                 Cvar_RegisterVariable (&gl_skyclip);
4063         }
4064         Cvar_RegisterVariable(&r_motionblur);
4065         Cvar_RegisterVariable(&r_motionblur_maxblur);
4066         Cvar_RegisterVariable(&r_motionblur_bmin);
4067         Cvar_RegisterVariable(&r_motionblur_vmin);
4068         Cvar_RegisterVariable(&r_motionblur_vmax);
4069         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4070         Cvar_RegisterVariable(&r_motionblur_randomize);
4071         Cvar_RegisterVariable(&r_damageblur);
4072         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4073         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4074         Cvar_RegisterVariable(&r_equalize_entities_by);
4075         Cvar_RegisterVariable(&r_equalize_entities_to);
4076         Cvar_RegisterVariable(&r_depthfirst);
4077         Cvar_RegisterVariable(&r_useinfinitefarclip);
4078         Cvar_RegisterVariable(&r_farclip_base);
4079         Cvar_RegisterVariable(&r_farclip_world);
4080         Cvar_RegisterVariable(&r_nearclip);
4081         Cvar_RegisterVariable(&r_deformvertexes);
4082         Cvar_RegisterVariable(&r_transparent);
4083         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4084         Cvar_RegisterVariable(&r_showoverdraw);
4085         Cvar_RegisterVariable(&r_showbboxes);
4086         Cvar_RegisterVariable(&r_showsurfaces);
4087         Cvar_RegisterVariable(&r_showtris);
4088         Cvar_RegisterVariable(&r_shownormals);
4089         Cvar_RegisterVariable(&r_showlighting);
4090         Cvar_RegisterVariable(&r_showshadowvolumes);
4091         Cvar_RegisterVariable(&r_showcollisionbrushes);
4092         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4093         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4094         Cvar_RegisterVariable(&r_showdisabledepthtest);
4095         Cvar_RegisterVariable(&r_drawportals);
4096         Cvar_RegisterVariable(&r_drawentities);
4097         Cvar_RegisterVariable(&r_draw2d);
4098         Cvar_RegisterVariable(&r_drawworld);
4099         Cvar_RegisterVariable(&r_cullentities_trace);
4100         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4101         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4102         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4103         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4104         Cvar_RegisterVariable(&r_drawviewmodel);
4105         Cvar_RegisterVariable(&r_drawexteriormodel);
4106         Cvar_RegisterVariable(&r_speeds);
4107         Cvar_RegisterVariable(&r_fullbrights);
4108         Cvar_RegisterVariable(&r_wateralpha);
4109         Cvar_RegisterVariable(&r_dynamic);
4110         Cvar_RegisterVariable(&r_fakelight);
4111         Cvar_RegisterVariable(&r_fakelight_intensity);
4112         Cvar_RegisterVariable(&r_fullbright);
4113         Cvar_RegisterVariable(&r_shadows);
4114         Cvar_RegisterVariable(&r_shadows_darken);
4115         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4116         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4117         Cvar_RegisterVariable(&r_shadows_throwdistance);
4118         Cvar_RegisterVariable(&r_shadows_throwdirection);
4119         Cvar_RegisterVariable(&r_shadows_focus);
4120         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4121         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4122         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4123         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4124         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4125         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4126         Cvar_RegisterVariable(&r_fog_exp2);
4127         Cvar_RegisterVariable(&r_fog_clear);
4128         Cvar_RegisterVariable(&r_drawfog);
4129         Cvar_RegisterVariable(&r_transparentdepthmasking);
4130         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4131         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4132         Cvar_RegisterVariable(&r_texture_dds_load);
4133         Cvar_RegisterVariable(&r_texture_dds_save);
4134         Cvar_RegisterVariable(&r_textureunits);
4135         Cvar_RegisterVariable(&gl_combine);
4136         Cvar_RegisterVariable(&r_viewfbo);
4137         Cvar_RegisterVariable(&r_viewscale);
4138         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4139         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4140         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4141         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4142         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4143         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4144         Cvar_RegisterVariable(&r_glsl);
4145         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4146         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4147         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4148         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4149         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4150         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4151         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4152         Cvar_RegisterVariable(&r_glsl_postprocess);
4153         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4154         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4155         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4156         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4157         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4158         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4159         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4160         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4161
4162         Cvar_RegisterVariable(&r_water);
4163         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4164         Cvar_RegisterVariable(&r_water_clippingplanebias);
4165         Cvar_RegisterVariable(&r_water_refractdistort);
4166         Cvar_RegisterVariable(&r_water_reflectdistort);
4167         Cvar_RegisterVariable(&r_water_scissormode);
4168         Cvar_RegisterVariable(&r_water_lowquality);
4169
4170         Cvar_RegisterVariable(&r_lerpsprites);
4171         Cvar_RegisterVariable(&r_lerpmodels);
4172         Cvar_RegisterVariable(&r_lerplightstyles);
4173         Cvar_RegisterVariable(&r_waterscroll);
4174         Cvar_RegisterVariable(&r_bloom);
4175         Cvar_RegisterVariable(&r_bloom_colorscale);
4176         Cvar_RegisterVariable(&r_bloom_brighten);
4177         Cvar_RegisterVariable(&r_bloom_blur);
4178         Cvar_RegisterVariable(&r_bloom_resolution);
4179         Cvar_RegisterVariable(&r_bloom_colorexponent);
4180         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4181         Cvar_RegisterVariable(&r_hdr);
4182         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4183         Cvar_RegisterVariable(&r_hdr_glowintensity);
4184         Cvar_RegisterVariable(&r_hdr_range);
4185         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4186         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4187         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4188         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4189         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4190         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4191         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4192         Cvar_RegisterVariable(&developer_texturelogging);
4193         Cvar_RegisterVariable(&gl_lightmaps);
4194         Cvar_RegisterVariable(&r_test);
4195         Cvar_RegisterVariable(&r_glsl_saturation);
4196         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4197         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4198         Cvar_RegisterVariable(&r_framedatasize);
4199         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4200                 Cvar_SetValue("r_fullbrights", 0);
4201         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4202
4203         Cvar_RegisterVariable(&r_track_sprites);
4204         Cvar_RegisterVariable(&r_track_sprites_flags);
4205         Cvar_RegisterVariable(&r_track_sprites_scalew);
4206         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4207         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4208         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4209         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4210         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4211 }
4212
4213 extern void R_Textures_Init(void);
4214 extern void GL_Draw_Init(void);
4215 extern void GL_Main_Init(void);
4216 extern void R_Shadow_Init(void);
4217 extern void R_Sky_Init(void);
4218 extern void GL_Surf_Init(void);
4219 extern void R_Particles_Init(void);
4220 extern void R_Explosion_Init(void);
4221 extern void gl_backend_init(void);
4222 extern void Sbar_Init(void);
4223 extern void R_LightningBeams_Init(void);
4224 extern void Mod_RenderInit(void);
4225 extern void Font_Init(void);
4226
4227 void Render_Init(void)
4228 {
4229         gl_backend_init();
4230         R_Textures_Init();
4231         GL_Main_Init();
4232         Font_Init();
4233         GL_Draw_Init();
4234         R_Shadow_Init();
4235         R_Sky_Init();
4236         GL_Surf_Init();
4237         Sbar_Init();
4238         R_Particles_Init();
4239         R_Explosion_Init();
4240         R_LightningBeams_Init();
4241         Mod_RenderInit();
4242 }
4243
4244 /*
4245 ===============
4246 GL_Init
4247 ===============
4248 */
4249 extern char *ENGINE_EXTENSIONS;
4250 void GL_Init (void)
4251 {
4252         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4253         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4254         gl_version = (const char *)qglGetString(GL_VERSION);
4255         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4256
4257         if (!gl_extensions)
4258                 gl_extensions = "";
4259         if (!gl_platformextensions)
4260                 gl_platformextensions = "";
4261
4262         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4263         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4264         Con_Printf("GL_VERSION: %s\n", gl_version);
4265         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4266         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4267
4268         VID_CheckExtensions();
4269
4270         // LordHavoc: report supported extensions
4271         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4272
4273         // clear to black (loading plaque will be seen over this)
4274         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4275 }
4276
4277 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4278 {
4279         int i;
4280         mplane_t *p;
4281         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4282         {
4283                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4284                 if (i == 4)
4285                         continue;
4286                 p = r_refdef.view.frustum + i;
4287                 switch(p->signbits)
4288                 {
4289                 default:
4290                 case 0:
4291                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4292                                 return true;
4293                         break;
4294                 case 1:
4295                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4296                                 return true;
4297                         break;
4298                 case 2:
4299                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4300                                 return true;
4301                         break;
4302                 case 3:
4303                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4304                                 return true;
4305                         break;
4306                 case 4:
4307                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4308                                 return true;
4309                         break;
4310                 case 5:
4311                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4312                                 return true;
4313                         break;
4314                 case 6:
4315                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4316                                 return true;
4317                         break;
4318                 case 7:
4319                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4320                                 return true;
4321                         break;
4322                 }
4323         }
4324         return false;
4325 }
4326
4327 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4328 {
4329         int i;
4330         const mplane_t *p;
4331         for (i = 0;i < numplanes;i++)
4332         {
4333                 p = planes + i;
4334                 switch(p->signbits)
4335                 {
4336                 default:
4337                 case 0:
4338                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4339                                 return true;
4340                         break;
4341                 case 1:
4342                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4343                                 return true;
4344                         break;
4345                 case 2:
4346                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4347                                 return true;
4348                         break;
4349                 case 3:
4350                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4351                                 return true;
4352                         break;
4353                 case 4:
4354                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4355                                 return true;
4356                         break;
4357                 case 5:
4358                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4359                                 return true;
4360                         break;
4361                 case 6:
4362                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4363                                 return true;
4364                         break;
4365                 case 7:
4366                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4367                                 return true;
4368                         break;
4369                 }
4370         }
4371         return false;
4372 }
4373
4374 //==================================================================================
4375
4376 // LordHavoc: this stores temporary data used within the same frame
4377
4378 typedef struct r_framedata_mem_s
4379 {
4380         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4381         size_t size; // how much usable space
4382         size_t current; // how much space in use
4383         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4384         size_t wantedsize; // how much space was allocated
4385         unsigned char *data; // start of real data (16byte aligned)
4386 }
4387 r_framedata_mem_t;
4388
4389 static r_framedata_mem_t *r_framedata_mem;
4390
4391 void R_FrameData_Reset(void)
4392 {
4393         while (r_framedata_mem)
4394         {
4395                 r_framedata_mem_t *next = r_framedata_mem->purge;
4396                 Mem_Free(r_framedata_mem);
4397                 r_framedata_mem = next;
4398         }
4399 }
4400
4401 void R_FrameData_Resize(void)
4402 {
4403         size_t wantedsize;
4404         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4405         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4406         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4407         {
4408                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4409                 newmem->wantedsize = wantedsize;
4410                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4411                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4412                 newmem->current = 0;
4413                 newmem->mark = 0;
4414                 newmem->purge = r_framedata_mem;
4415                 r_framedata_mem = newmem;
4416         }
4417 }
4418
4419 void R_FrameData_NewFrame(void)
4420 {
4421         R_FrameData_Resize();
4422         if (!r_framedata_mem)
4423                 return;
4424         // if we ran out of space on the last frame, free the old memory now
4425         while (r_framedata_mem->purge)
4426         {
4427                 // repeatedly remove the second item in the list, leaving only head
4428                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4429                 Mem_Free(r_framedata_mem->purge);
4430                 r_framedata_mem->purge = next;
4431         }
4432         // reset the current mem pointer
4433         r_framedata_mem->current = 0;
4434         r_framedata_mem->mark = 0;
4435 }
4436
4437 void *R_FrameData_Alloc(size_t size)
4438 {
4439         void *data;
4440
4441         // align to 16 byte boundary - the data pointer is already aligned, so we
4442         // only need to ensure the size of every allocation is also aligned
4443         size = (size + 15) & ~15;
4444
4445         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4446         {
4447                 // emergency - we ran out of space, allocate more memory
4448                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4449                 R_FrameData_Resize();
4450         }
4451
4452         data = r_framedata_mem->data + r_framedata_mem->current;
4453         r_framedata_mem->current += size;
4454
4455         // count the usage for stats
4456         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4457         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4458
4459         return (void *)data;
4460 }
4461
4462 void *R_FrameData_Store(size_t size, void *data)
4463 {
4464         void *d = R_FrameData_Alloc(size);
4465         if (d && data)
4466                 memcpy(d, data, size);
4467         return d;
4468 }
4469
4470 void R_FrameData_SetMark(void)
4471 {
4472         if (!r_framedata_mem)
4473                 return;
4474         r_framedata_mem->mark = r_framedata_mem->current;
4475 }
4476
4477 void R_FrameData_ReturnToMark(void)
4478 {
4479         if (!r_framedata_mem)
4480                 return;
4481         r_framedata_mem->current = r_framedata_mem->mark;
4482 }
4483
4484 //==================================================================================
4485
4486 // LordHavoc: animcache originally written by Echon, rewritten since then
4487
4488 /**
4489  * Animation cache prevents re-generating mesh data for an animated model
4490  * multiple times in one frame for lighting, shadowing, reflections, etc.
4491  */
4492
4493 void R_AnimCache_Free(void)
4494 {
4495 }
4496
4497 void R_AnimCache_ClearCache(void)
4498 {
4499         int i;
4500         entity_render_t *ent;
4501
4502         for (i = 0;i < r_refdef.scene.numentities;i++)
4503         {
4504                 ent = r_refdef.scene.entities[i];
4505                 ent->animcache_vertex3f = NULL;
4506                 ent->animcache_normal3f = NULL;
4507                 ent->animcache_svector3f = NULL;
4508                 ent->animcache_tvector3f = NULL;
4509                 ent->animcache_vertexmesh = NULL;
4510                 ent->animcache_vertex3fbuffer = NULL;
4511                 ent->animcache_vertexmeshbuffer = NULL;
4512         }
4513 }
4514
4515 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4516 {
4517         int i;
4518
4519         // check if we need the meshbuffers
4520         if (!vid.useinterleavedarrays)
4521                 return;
4522
4523         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4524                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4525         // TODO: upload vertex3f buffer?
4526         if (ent->animcache_vertexmesh)
4527         {
4528                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4529                 for (i = 0;i < numvertices;i++)
4530                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4531                 if (ent->animcache_svector3f)
4532                         for (i = 0;i < numvertices;i++)
4533                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4534                 if (ent->animcache_tvector3f)
4535                         for (i = 0;i < numvertices;i++)
4536                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4537                 if (ent->animcache_normal3f)
4538                         for (i = 0;i < numvertices;i++)
4539                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4540                 // TODO: upload vertexmeshbuffer?
4541         }
4542 }
4543
4544 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4545 {
4546         dp_model_t *model = ent->model;
4547         int numvertices;
4548         // see if it's already cached this frame
4549         if (ent->animcache_vertex3f)
4550         {
4551                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4552                 if (wantnormals || wanttangents)
4553                 {
4554                         if (ent->animcache_normal3f)
4555                                 wantnormals = false;
4556                         if (ent->animcache_svector3f)
4557                                 wanttangents = false;
4558                         if (wantnormals || wanttangents)
4559                         {
4560                                 numvertices = model->surfmesh.num_vertices;
4561                                 if (wantnormals)
4562                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563                                 if (wanttangents)
4564                                 {
4565                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567                                 }
4568                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4569                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4570                         }
4571                 }
4572         }
4573         else
4574         {
4575                 // see if this ent is worth caching
4576                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4577                         return false;
4578                 // get some memory for this entity and generate mesh data
4579                 numvertices = model->surfmesh.num_vertices;
4580                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4581                 if (wantnormals)
4582                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4583                 if (wanttangents)
4584                 {
4585                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4586                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4587                 }
4588                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4589                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4590         }
4591         return true;
4592 }
4593
4594 void R_AnimCache_CacheVisibleEntities(void)
4595 {
4596         int i;
4597         qboolean wantnormals = true;
4598         qboolean wanttangents = !r_showsurfaces.integer;
4599
4600         switch(vid.renderpath)
4601         {
4602         case RENDERPATH_GL20:
4603         case RENDERPATH_D3D9:
4604         case RENDERPATH_D3D10:
4605         case RENDERPATH_D3D11:
4606         case RENDERPATH_GLES2:
4607                 break;
4608         case RENDERPATH_GL11:
4609         case RENDERPATH_GL13:
4610         case RENDERPATH_GLES1:
4611                 wanttangents = false;
4612                 break;
4613         case RENDERPATH_SOFT:
4614                 break;
4615         }
4616
4617         if (r_shownormals.integer)
4618                 wanttangents = wantnormals = true;
4619
4620         // TODO: thread this
4621         // NOTE: R_PrepareRTLights() also caches entities
4622
4623         for (i = 0;i < r_refdef.scene.numentities;i++)
4624                 if (r_refdef.viewcache.entityvisible[i])
4625                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4626 }
4627
4628 //==================================================================================
4629
4630 static void R_View_UpdateEntityLighting (void)
4631 {
4632         int i;
4633         entity_render_t *ent;
4634         vec3_t tempdiffusenormal, avg;
4635         vec_t f, fa, fd, fdd;
4636         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4637
4638         for (i = 0;i < r_refdef.scene.numentities;i++)
4639         {
4640                 ent = r_refdef.scene.entities[i];
4641
4642                 // skip unseen models
4643                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4644                         continue;
4645
4646                 // skip bsp models
4647                 if (ent->model && ent->model->brush.num_leafs)
4648                 {
4649                         // TODO: use modellight for r_ambient settings on world?
4650                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4651                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4652                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4653                         continue;
4654                 }
4655
4656                 // fetch the lighting from the worldmodel data
4657                 VectorClear(ent->modellight_ambient);
4658                 VectorClear(ent->modellight_diffuse);
4659                 VectorClear(tempdiffusenormal);
4660                 if (ent->flags & RENDER_LIGHT)
4661                 {
4662                         vec3_t org;
4663                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4664
4665                         // complete lightning for lit sprites
4666                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4667                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4668                         {
4669                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4670                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4671                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4672                         }
4673                         else
4674                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4675
4676                         if(ent->flags & RENDER_EQUALIZE)
4677                         {
4678                                 // first fix up ambient lighting...
4679                                 if(r_equalize_entities_minambient.value > 0)
4680                                 {
4681                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4682                                         if(fd > 0)
4683                                         {
4684                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4685                                                 if(fa < r_equalize_entities_minambient.value * fd)
4686                                                 {
4687                                                         // solve:
4688                                                         //   fa'/fd' = minambient
4689                                                         //   fa'+0.25*fd' = fa+0.25*fd
4690                                                         //   ...
4691                                                         //   fa' = fd' * minambient
4692                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4693                                                         //   ...
4694                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4695                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4696                                                         //   ...
4697                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4698                                                         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
4699                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4700                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4701                                                 }
4702                                         }
4703                                 }
4704
4705                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4706                                 {
4707                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4708                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4709                                         f = fa + 0.25 * fd;
4710                                         if(f > 0)
4711                                         {
4712                                                 // adjust brightness and saturation to target
4713                                                 avg[0] = avg[1] = avg[2] = fa / f;
4714                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4715                                                 avg[0] = avg[1] = avg[2] = fd / f;
4716                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4717                                         }
4718                                 }
4719                         }
4720                 }
4721                 else // highly rare
4722                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4723
4724                 // move the light direction into modelspace coordinates for lighting code
4725                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4726                 if(VectorLength2(ent->modellight_lightdir) == 0)
4727                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4728                 VectorNormalize(ent->modellight_lightdir);
4729         }
4730 }
4731
4732 #define MAX_LINEOFSIGHTTRACES 64
4733
4734 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4735 {
4736         int i;
4737         vec3_t boxmins, boxmaxs;
4738         vec3_t start;
4739         vec3_t end;
4740         dp_model_t *model = r_refdef.scene.worldmodel;
4741
4742         if (!model || !model->brush.TraceLineOfSight)
4743                 return true;
4744
4745         // expand the box a little
4746         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4747         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4748         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4749         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4750         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4751         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4752
4753         // return true if eye is inside enlarged box
4754         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4755                 return true;
4756
4757         // try center
4758         VectorCopy(eye, start);
4759         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4760         if (model->brush.TraceLineOfSight(model, start, end))
4761                 return true;
4762
4763         // try various random positions
4764         for (i = 0;i < numsamples;i++)
4765         {
4766                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4767                 if (model->brush.TraceLineOfSight(model, start, end))
4768                         return true;
4769         }
4770
4771         return false;
4772 }
4773
4774
4775 static void R_View_UpdateEntityVisible (void)
4776 {
4777         int i;
4778         int renderimask;
4779         int samples;
4780         entity_render_t *ent;
4781
4782         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4783                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4784                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4785                 :                                                          RENDER_EXTERIORMODEL;
4786         if (!r_drawviewmodel.integer)
4787                 renderimask |= RENDER_VIEWMODEL;
4788         if (!r_drawexteriormodel.integer)
4789                 renderimask |= RENDER_EXTERIORMODEL;
4790         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4791         {
4792                 // worldmodel can check visibility
4793                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4794                 for (i = 0;i < r_refdef.scene.numentities;i++)
4795                 {
4796                         ent = r_refdef.scene.entities[i];
4797                         if (!(ent->flags & renderimask))
4798                         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)))
4799                         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))
4800                                 r_refdef.viewcache.entityvisible[i] = true;
4801                 }
4802         }
4803         else
4804         {
4805                 // no worldmodel or it can't check visibility
4806                 for (i = 0;i < r_refdef.scene.numentities;i++)
4807                 {
4808                         ent = r_refdef.scene.entities[i];
4809                         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));
4810                 }
4811         }
4812         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4813                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4814         {
4815                 for (i = 0;i < r_refdef.scene.numentities;i++)
4816                 {
4817                         if (!r_refdef.viewcache.entityvisible[i])
4818                                 continue;
4819                         ent = r_refdef.scene.entities[i];
4820                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4821                         {
4822                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4823                                 if (samples < 0)
4824                                         continue; // temp entities do pvs only
4825                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4826                                         ent->last_trace_visibility = realtime;
4827                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4828                                         r_refdef.viewcache.entityvisible[i] = 0;
4829                         }
4830                 }
4831         }
4832 }
4833
4834 /// only used if skyrendermasked, and normally returns false
4835 int R_DrawBrushModelsSky (void)
4836 {
4837         int i, sky;
4838         entity_render_t *ent;
4839
4840         sky = false;
4841         for (i = 0;i < r_refdef.scene.numentities;i++)
4842         {
4843                 if (!r_refdef.viewcache.entityvisible[i])
4844                         continue;
4845                 ent = r_refdef.scene.entities[i];
4846                 if (!ent->model || !ent->model->DrawSky)
4847                         continue;
4848                 ent->model->DrawSky(ent);
4849                 sky = true;
4850         }
4851         return sky;
4852 }
4853
4854 static void R_DrawNoModel(entity_render_t *ent);
4855 static void R_DrawModels(void)
4856 {
4857         int i;
4858         entity_render_t *ent;
4859
4860         for (i = 0;i < r_refdef.scene.numentities;i++)
4861         {
4862                 if (!r_refdef.viewcache.entityvisible[i])
4863                         continue;
4864                 ent = r_refdef.scene.entities[i];
4865                 r_refdef.stats.entities++;
4866                 /*
4867                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4868                 {
4869                         vec3_t f, l, u, o;
4870                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4871                         Con_Printf("R_DrawModels\n");
4872                         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]);
4873                         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);
4874                         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);
4875                 }
4876                 */
4877                 if (ent->model && ent->model->Draw != NULL)
4878                         ent->model->Draw(ent);
4879                 else
4880                         R_DrawNoModel(ent);
4881         }
4882 }
4883
4884 static void R_DrawModelsDepth(void)
4885 {
4886         int i;
4887         entity_render_t *ent;
4888
4889         for (i = 0;i < r_refdef.scene.numentities;i++)
4890         {
4891                 if (!r_refdef.viewcache.entityvisible[i])
4892                         continue;
4893                 ent = r_refdef.scene.entities[i];
4894                 if (ent->model && ent->model->DrawDepth != NULL)
4895                         ent->model->DrawDepth(ent);
4896         }
4897 }
4898
4899 static void R_DrawModelsDebug(void)
4900 {
4901         int i;
4902         entity_render_t *ent;
4903
4904         for (i = 0;i < r_refdef.scene.numentities;i++)
4905         {
4906                 if (!r_refdef.viewcache.entityvisible[i])
4907                         continue;
4908                 ent = r_refdef.scene.entities[i];
4909                 if (ent->model && ent->model->DrawDebug != NULL)
4910                         ent->model->DrawDebug(ent);
4911         }
4912 }
4913
4914 static void R_DrawModelsAddWaterPlanes(void)
4915 {
4916         int i;
4917         entity_render_t *ent;
4918
4919         for (i = 0;i < r_refdef.scene.numentities;i++)
4920         {
4921                 if (!r_refdef.viewcache.entityvisible[i])
4922                         continue;
4923                 ent = r_refdef.scene.entities[i];
4924                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4925                         ent->model->DrawAddWaterPlanes(ent);
4926         }
4927 }
4928
4929 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4930 {
4931         if (r_hdr_irisadaptation.integer)
4932         {
4933                 vec3_t ambient;
4934                 vec3_t diffuse;
4935                 vec3_t diffusenormal;
4936                 vec_t brightness;
4937                 vec_t goal;
4938                 vec_t adjust;
4939                 vec_t current;
4940                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4941                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4942                 brightness = max(0.0000001f, brightness);
4943                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4944                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4945                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4946                 current = r_hdr_irisadaptation_value.value;
4947                 if (current < goal)
4948                         current = min(current + adjust, goal);
4949                 else if (current > goal)
4950                         current = max(current - adjust, goal);
4951                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4952                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4953         }
4954         else if (r_hdr_irisadaptation_value.value != 1.0f)
4955                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4956 }
4957
4958 static void R_View_SetFrustum(const int *scissor)
4959 {
4960         int i;
4961         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4962         vec3_t forward, left, up, origin, v;
4963
4964         if(scissor)
4965         {
4966                 // flipped x coordinates (because x points left here)
4967                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4968                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4969
4970                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4971                 switch(vid.renderpath)
4972                 {
4973                         case RENDERPATH_D3D9:
4974                         case RENDERPATH_D3D10:
4975                         case RENDERPATH_D3D11:
4976                                 // non-flipped y coordinates
4977                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4978                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4979                                 break;
4980                         case RENDERPATH_SOFT:
4981                         case RENDERPATH_GL11:
4982                         case RENDERPATH_GL13:
4983                         case RENDERPATH_GL20:
4984                         case RENDERPATH_GLES1:
4985                         case RENDERPATH_GLES2:
4986                                 // non-flipped y coordinates
4987                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4988                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4989                                 break;
4990                 }
4991         }
4992
4993         // we can't trust r_refdef.view.forward and friends in reflected scenes
4994         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4995
4996 #if 0
4997         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4998         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4999         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5000         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5001         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5002         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5003         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5004         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5005         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5006         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5007         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5008         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5009 #endif
5010
5011 #if 0
5012         zNear = r_refdef.nearclip;
5013         nudge = 1.0 - 1.0 / (1<<23);
5014         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5015         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5016         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5017         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5018         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5019         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5020         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5021         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5022 #endif
5023
5024
5025
5026 #if 0
5027         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5028         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5029         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5030         r_refdef.view.frustum[0].dist = m[15] - m[12];
5031
5032         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5033         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5034         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5035         r_refdef.view.frustum[1].dist = m[15] + m[12];
5036
5037         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5038         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5039         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5040         r_refdef.view.frustum[2].dist = m[15] - m[13];
5041
5042         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5043         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5044         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5045         r_refdef.view.frustum[3].dist = m[15] + m[13];
5046
5047         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5048         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5049         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5050         r_refdef.view.frustum[4].dist = m[15] - m[14];
5051
5052         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5053         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5054         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5055         r_refdef.view.frustum[5].dist = m[15] + m[14];
5056 #endif
5057
5058         if (r_refdef.view.useperspective)
5059         {
5060                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5061                 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]);
5062                 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]);
5063                 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]);
5064                 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]);
5065
5066                 // then the normals from the corners relative to origin
5067                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5068                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5069                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5070                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5071
5072                 // in a NORMAL view, forward cross left == up
5073                 // in a REFLECTED view, forward cross left == down
5074                 // so our cross products above need to be adjusted for a left handed coordinate system
5075                 CrossProduct(forward, left, v);
5076                 if(DotProduct(v, up) < 0)
5077                 {
5078                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5079                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5080                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5081                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5082                 }
5083
5084                 // Leaving those out was a mistake, those were in the old code, and they
5085                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5086                 // I couldn't reproduce it after adding those normalizations. --blub
5087                 VectorNormalize(r_refdef.view.frustum[0].normal);
5088                 VectorNormalize(r_refdef.view.frustum[1].normal);
5089                 VectorNormalize(r_refdef.view.frustum[2].normal);
5090                 VectorNormalize(r_refdef.view.frustum[3].normal);
5091
5092                 // make the corners absolute
5093                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5094                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5095                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5096                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5097
5098                 // one more normal
5099                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5100
5101                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5102                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5103                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5104                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5105                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5106         }
5107         else
5108         {
5109                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5110                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5111                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5112                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5113                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5114                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5115                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5116                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5117                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5118                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5119         }
5120         r_refdef.view.numfrustumplanes = 5;
5121
5122         if (r_refdef.view.useclipplane)
5123         {
5124                 r_refdef.view.numfrustumplanes = 6;
5125                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5126         }
5127
5128         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5129                 PlaneClassify(r_refdef.view.frustum + i);
5130
5131         // LordHavoc: note to all quake engine coders, Quake had a special case
5132         // for 90 degrees which assumed a square view (wrong), so I removed it,
5133         // Quake2 has it disabled as well.
5134
5135         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5136         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5137         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5138         //PlaneClassify(&frustum[0]);
5139
5140         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5141         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5142         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5143         //PlaneClassify(&frustum[1]);
5144
5145         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5146         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5147         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5148         //PlaneClassify(&frustum[2]);
5149
5150         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5151         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5152         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5153         //PlaneClassify(&frustum[3]);
5154
5155         // nearclip plane
5156         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5157         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5158         //PlaneClassify(&frustum[4]);
5159 }
5160
5161 void R_View_UpdateWithScissor(const int *myscissor)
5162 {
5163         R_Main_ResizeViewCache();
5164         R_View_SetFrustum(myscissor);
5165         R_View_WorldVisibility(r_refdef.view.useclipplane);
5166         R_View_UpdateEntityVisible();
5167         R_View_UpdateEntityLighting();
5168 }
5169
5170 void R_View_Update(void)
5171 {
5172         R_Main_ResizeViewCache();
5173         R_View_SetFrustum(NULL);
5174         R_View_WorldVisibility(r_refdef.view.useclipplane);
5175         R_View_UpdateEntityVisible();
5176         R_View_UpdateEntityLighting();
5177 }
5178
5179 float viewscalefpsadjusted = 1.0f;
5180
5181 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5182 {
5183         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5184         scale = bound(0.03125f, scale, 1.0f);
5185         *outwidth = (int)ceil(width * scale);
5186         *outheight = (int)ceil(height * scale);
5187 }
5188
5189 void R_Mesh_SetMainRenderTargets(void)
5190 {
5191         if (r_bloomstate.fbo_framebuffer)
5192                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5193         else
5194                 R_Mesh_ResetRenderTargets();
5195 }
5196
5197 void R_SetupView(qboolean allowwaterclippingplane)
5198 {
5199         const float *customclipplane = NULL;
5200         float plane[4];
5201         int scaledwidth, scaledheight;
5202         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5203         {
5204                 // LordHavoc: couldn't figure out how to make this approach the
5205                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5206                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5207                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5208                         dist = r_refdef.view.clipplane.dist;
5209                 plane[0] = r_refdef.view.clipplane.normal[0];
5210                 plane[1] = r_refdef.view.clipplane.normal[1];
5211                 plane[2] = r_refdef.view.clipplane.normal[2];
5212                 plane[3] = -dist;
5213                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5214         }
5215
5216         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5217         if (!r_refdef.view.useperspective)
5218                 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);
5219         else if (vid.stencil && r_useinfinitefarclip.integer)
5220                 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);
5221         else
5222                 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);
5223         R_Mesh_SetMainRenderTargets();
5224         R_SetViewport(&r_refdef.view.viewport);
5225         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5226         {
5227                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5228                 float screenplane[4];
5229                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5230                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5231                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5232                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5233                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5234         }
5235 }
5236
5237 void R_EntityMatrix(const matrix4x4_t *matrix)
5238 {
5239         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5240         {
5241                 gl_modelmatrixchanged = false;
5242                 gl_modelmatrix = *matrix;
5243                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5244                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5245                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5246                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5247                 CHECKGLERROR
5248                 switch(vid.renderpath)
5249                 {
5250                 case RENDERPATH_D3D9:
5251 #ifdef SUPPORTD3D
5252                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5253                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5254 #endif
5255                         break;
5256                 case RENDERPATH_D3D10:
5257                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5258                         break;
5259                 case RENDERPATH_D3D11:
5260                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5261                         break;
5262                 case RENDERPATH_GL11:
5263                 case RENDERPATH_GL13:
5264                 case RENDERPATH_GLES1:
5265                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5266                         break;
5267                 case RENDERPATH_SOFT:
5268                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5269                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5270                         break;
5271                 case RENDERPATH_GL20:
5272                 case RENDERPATH_GLES2:
5273                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5274                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5275                         break;
5276                 }
5277         }
5278 }
5279
5280 void R_ResetViewRendering2D(void)
5281 {
5282         r_viewport_t viewport;
5283         DrawQ_Finish();
5284
5285         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5286         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);
5287         R_Mesh_ResetRenderTargets();
5288         R_SetViewport(&viewport);
5289         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5290         GL_Color(1, 1, 1, 1);
5291         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5292         GL_BlendFunc(GL_ONE, GL_ZERO);
5293         GL_ScissorTest(false);
5294         GL_DepthMask(false);
5295         GL_DepthRange(0, 1);
5296         GL_DepthTest(false);
5297         GL_DepthFunc(GL_LEQUAL);
5298         R_EntityMatrix(&identitymatrix);
5299         R_Mesh_ResetTextureState();
5300         GL_PolygonOffset(0, 0);
5301         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5302         switch(vid.renderpath)
5303         {
5304         case RENDERPATH_GL11:
5305         case RENDERPATH_GL13:
5306         case RENDERPATH_GL20:
5307         case RENDERPATH_GLES1:
5308         case RENDERPATH_GLES2:
5309                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5310                 break;
5311         case RENDERPATH_D3D9:
5312         case RENDERPATH_D3D10:
5313         case RENDERPATH_D3D11:
5314         case RENDERPATH_SOFT:
5315                 break;
5316         }
5317         GL_CullFace(GL_NONE);
5318 }
5319
5320 void R_ResetViewRendering3D(void)
5321 {
5322         DrawQ_Finish();
5323
5324         R_SetupView(true);
5325         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5326         GL_Color(1, 1, 1, 1);
5327         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5328         GL_BlendFunc(GL_ONE, GL_ZERO);
5329         GL_ScissorTest(true);
5330         GL_DepthMask(true);
5331         GL_DepthRange(0, 1);
5332         GL_DepthTest(true);
5333         GL_DepthFunc(GL_LEQUAL);
5334         R_EntityMatrix(&identitymatrix);
5335         R_Mesh_ResetTextureState();
5336         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5337         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5338         switch(vid.renderpath)
5339         {
5340         case RENDERPATH_GL11:
5341         case RENDERPATH_GL13:
5342         case RENDERPATH_GL20:
5343         case RENDERPATH_GLES1:
5344         case RENDERPATH_GLES2:
5345                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5346                 break;
5347         case RENDERPATH_D3D9:
5348         case RENDERPATH_D3D10:
5349         case RENDERPATH_D3D11:
5350         case RENDERPATH_SOFT:
5351                 break;
5352         }
5353         GL_CullFace(r_refdef.view.cullface_back);
5354 }
5355
5356 /*
5357 ================
5358 R_RenderView_UpdateViewVectors
5359 ================
5360 */
5361 static void R_RenderView_UpdateViewVectors(void)
5362 {
5363         // break apart the view matrix into vectors for various purposes
5364         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5365         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5366         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5367         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5368         // make an inverted copy of the view matrix for tracking sprites
5369         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5370 }
5371
5372 void R_RenderScene(void);
5373 void R_RenderWaterPlanes(void);
5374
5375 static void R_Water_StartFrame(void)
5376 {
5377         int i;
5378         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5379         r_waterstate_waterplane_t *p;
5380
5381         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5382                 return;
5383
5384         switch(vid.renderpath)
5385         {
5386         case RENDERPATH_GL20:
5387         case RENDERPATH_D3D9:
5388         case RENDERPATH_D3D10:
5389         case RENDERPATH_D3D11:
5390         case RENDERPATH_SOFT:
5391         case RENDERPATH_GLES2:
5392                 break;
5393         case RENDERPATH_GL11:
5394         case RENDERPATH_GL13:
5395         case RENDERPATH_GLES1:
5396                 return;
5397         }
5398
5399         // set waterwidth and waterheight to the water resolution that will be
5400         // used (often less than the screen resolution for faster rendering)
5401         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5402
5403         // calculate desired texture sizes
5404         // can't use water if the card does not support the texture size
5405         if (!r_water.integer || r_showsurfaces.integer)
5406                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5407         else if (vid.support.arb_texture_non_power_of_two)
5408         {
5409                 texturewidth = waterwidth;
5410                 textureheight = waterheight;
5411                 camerawidth = waterwidth;
5412                 cameraheight = waterheight;
5413         }
5414         else
5415         {
5416                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5417                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5418                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5419                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5420         }
5421
5422         // allocate textures as needed
5423         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5424         {
5425                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5426                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5427                 {
5428                         if (p->texture_refraction)
5429                                 R_FreeTexture(p->texture_refraction);
5430                         p->texture_refraction = NULL;
5431                         if (p->texture_reflection)
5432                                 R_FreeTexture(p->texture_reflection);
5433                         p->texture_reflection = NULL;
5434                         if (p->texture_camera)
5435                                 R_FreeTexture(p->texture_camera);
5436                         p->texture_camera = NULL;
5437                 }
5438                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5439                 r_waterstate.texturewidth = texturewidth;
5440                 r_waterstate.textureheight = textureheight;
5441                 r_waterstate.camerawidth = camerawidth;
5442                 r_waterstate.cameraheight = cameraheight;
5443         }
5444
5445         if (r_waterstate.texturewidth)
5446         {
5447                 int scaledwidth, scaledheight;
5448
5449                 r_waterstate.enabled = true;
5450
5451                 // when doing a reduced render (HDR) we want to use a smaller area
5452                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5453                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5454                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5455
5456                 // set up variables that will be used in shader setup
5457                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5458                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5459                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5460                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5461         }
5462
5463         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5464         r_waterstate.numwaterplanes = 0;
5465 }
5466
5467 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5468 {
5469         int triangleindex, planeindex;
5470         const int *e;
5471         vec3_t vert[3];
5472         vec3_t normal;
5473         vec3_t center;
5474         mplane_t plane;
5475         r_waterstate_waterplane_t *p;
5476         texture_t *t = R_GetCurrentTexture(surface->texture);
5477
5478         // just use the first triangle with a valid normal for any decisions
5479         VectorClear(normal);
5480         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5481         {
5482                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5483                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5484                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5485                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5486                 if (VectorLength2(normal) >= 0.001)
5487                         break;
5488         }
5489
5490         VectorCopy(normal, plane.normal);
5491         VectorNormalize(plane.normal);
5492         plane.dist = DotProduct(vert[0], plane.normal);
5493         PlaneClassify(&plane);
5494         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5495         {
5496                 // skip backfaces (except if nocullface is set)
5497                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5498                         return;
5499                 VectorNegate(plane.normal, plane.normal);
5500                 plane.dist *= -1;
5501                 PlaneClassify(&plane);
5502         }
5503
5504
5505         // find a matching plane if there is one
5506         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5507                 if(p->camera_entity == t->camera_entity)
5508                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5509                                 break;
5510         if (planeindex >= r_waterstate.maxwaterplanes)
5511                 return; // nothing we can do, out of planes
5512
5513         // if this triangle does not fit any known plane rendered this frame, add one
5514         if (planeindex >= r_waterstate.numwaterplanes)
5515         {
5516                 // store the new plane
5517                 r_waterstate.numwaterplanes++;
5518                 p->plane = plane;
5519                 // clear materialflags and pvs
5520                 p->materialflags = 0;
5521                 p->pvsvalid = false;
5522                 p->camera_entity = t->camera_entity;
5523                 VectorCopy(surface->mins, p->mins);
5524                 VectorCopy(surface->maxs, p->maxs);
5525         }
5526         else
5527         {
5528                 // merge mins/maxs
5529                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5530                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5531                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5532                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5533                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5534                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5535         }
5536         // merge this surface's materialflags into the waterplane
5537         p->materialflags |= t->currentmaterialflags;
5538         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5539         {
5540                 // merge this surface's PVS into the waterplane
5541                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5542                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5543                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5544                 {
5545                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5546                         p->pvsvalid = true;
5547                 }
5548         }
5549 }
5550
5551 extern cvar_t r_drawparticles;
5552 extern cvar_t r_drawdecals;
5553
5554 static void R_Water_ProcessPlanes(void)
5555 {
5556         int myscissor[4];
5557         r_refdef_view_t originalview;
5558         r_refdef_view_t myview;
5559         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;
5560         r_waterstate_waterplane_t *p;
5561         vec3_t visorigin;
5562
5563         originalview = r_refdef.view;
5564
5565         // lowquality hack, temporarily shut down some cvars and restore afterwards
5566         qualityreduction = r_water_lowquality.integer;
5567         if (qualityreduction > 0)
5568         {
5569                 if (qualityreduction >= 1)
5570                 {
5571                         old_r_shadows = r_shadows.integer;
5572                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5573                         old_r_dlight = r_shadow_realtime_dlight.integer;
5574                         Cvar_SetValueQuick(&r_shadows, 0);
5575                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5576                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5577                 }
5578                 if (qualityreduction >= 2)
5579                 {
5580                         old_r_dynamic = r_dynamic.integer;
5581                         old_r_particles = r_drawparticles.integer;
5582                         old_r_decals = r_drawdecals.integer;
5583                         Cvar_SetValueQuick(&r_dynamic, 0);
5584                         Cvar_SetValueQuick(&r_drawparticles, 0);
5585                         Cvar_SetValueQuick(&r_drawdecals, 0);
5586                 }
5587         }
5588
5589         // make sure enough textures are allocated
5590         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5591         {
5592                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5593                 {
5594                         if (!p->texture_refraction)
5595                                 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);
5596                         if (!p->texture_refraction)
5597                                 goto error;
5598                 }
5599                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5600                 {
5601                         if (!p->texture_camera)
5602                                 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);
5603                         if (!p->texture_camera)
5604                                 goto error;
5605                 }
5606
5607                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5608                 {
5609                         if (!p->texture_reflection)
5610                                 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);
5611                         if (!p->texture_reflection)
5612                                 goto error;
5613                 }
5614         }
5615
5616         // render views
5617         r_refdef.view = originalview;
5618         r_refdef.view.showdebug = false;
5619         r_refdef.view.width = r_waterstate.waterwidth;
5620         r_refdef.view.height = r_waterstate.waterheight;
5621         r_refdef.view.useclipplane = true;
5622         myview = r_refdef.view;
5623         r_waterstate.renderingscene = true;
5624         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5625         {
5626                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5627                 {
5628                         r_refdef.view = myview;
5629                         if(r_water_scissormode.integer)
5630                         {
5631                                 R_SetupView(true);
5632                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5633                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5634                         }
5635
5636                         // render reflected scene and copy into texture
5637                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5638                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5639                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5640                         r_refdef.view.clipplane = p->plane;
5641
5642                         // reverse the cullface settings for this render
5643                         r_refdef.view.cullface_front = GL_FRONT;
5644                         r_refdef.view.cullface_back = GL_BACK;
5645                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5646                         {
5647                                 r_refdef.view.usecustompvs = true;
5648                                 if (p->pvsvalid)
5649                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5650                                 else
5651                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5652                         }
5653
5654                         R_ResetViewRendering3D();
5655                         R_ClearScreen(r_refdef.fogenabled);
5656                         if(r_water_scissormode.integer & 2)
5657                                 R_View_UpdateWithScissor(myscissor);
5658                         else
5659                                 R_View_Update();
5660                         if(r_water_scissormode.integer & 1)
5661                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5662                         R_RenderScene();
5663
5664                         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);
5665                 }
5666
5667                 // render the normal view scene and copy into texture
5668                 // (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)
5669                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5670                 {
5671                         r_refdef.view = myview;
5672                         if(r_water_scissormode.integer)
5673                         {
5674                                 R_SetupView(true);
5675                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5676                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5677                         }
5678
5679                         r_waterstate.renderingrefraction = true;
5680
5681                         r_refdef.view.clipplane = p->plane;
5682                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5683                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5684
5685                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5686                         {
5687                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5688                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5689                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5690                                 R_RenderView_UpdateViewVectors();
5691                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5692                                 {
5693                                         r_refdef.view.usecustompvs = true;
5694                                         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);
5695                                 }
5696                         }
5697
5698                         PlaneClassify(&r_refdef.view.clipplane);
5699
5700                         R_ResetViewRendering3D();
5701                         R_ClearScreen(r_refdef.fogenabled);
5702                         if(r_water_scissormode.integer & 2)
5703                                 R_View_UpdateWithScissor(myscissor);
5704                         else
5705                                 R_View_Update();
5706                         if(r_water_scissormode.integer & 1)
5707                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5708                         R_RenderScene();
5709
5710                         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);
5711                         r_waterstate.renderingrefraction = false;
5712                 }
5713                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5714                 {
5715                         r_refdef.view = myview;
5716
5717                         r_refdef.view.clipplane = p->plane;
5718                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5719                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5720
5721                         r_refdef.view.width = r_waterstate.camerawidth;
5722                         r_refdef.view.height = r_waterstate.cameraheight;
5723                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5724                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5725
5726                         if(p->camera_entity)
5727                         {
5728                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5729                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5730                         }
5731
5732                         // note: all of the view is used for displaying... so
5733                         // there is no use in scissoring
5734
5735                         // reverse the cullface settings for this render
5736                         r_refdef.view.cullface_front = GL_FRONT;
5737                         r_refdef.view.cullface_back = GL_BACK;
5738                         // also reverse the view matrix
5739                         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
5740                         R_RenderView_UpdateViewVectors();
5741                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5742                         {
5743                                 r_refdef.view.usecustompvs = true;
5744                                 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);
5745                         }
5746                         
5747                         // camera needs no clipplane
5748                         r_refdef.view.useclipplane = false;
5749
5750                         PlaneClassify(&r_refdef.view.clipplane);
5751
5752                         R_ResetViewRendering3D();
5753                         R_ClearScreen(r_refdef.fogenabled);
5754                         R_View_Update();
5755                         R_RenderScene();
5756
5757                         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);
5758                         r_waterstate.renderingrefraction = false;
5759                 }
5760
5761         }
5762         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5763         r_waterstate.renderingscene = false;
5764         r_refdef.view = originalview;
5765         R_ResetViewRendering3D();
5766         R_ClearScreen(r_refdef.fogenabled);
5767         R_View_Update();
5768         goto finish;
5769 error:
5770         r_refdef.view = originalview;
5771         r_waterstate.renderingscene = false;
5772         Cvar_SetValueQuick(&r_water, 0);
5773         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5774 finish:
5775         // lowquality hack, restore cvars
5776         if (qualityreduction > 0)
5777         {
5778                 if (qualityreduction >= 1)
5779                 {
5780                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5781                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5782                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5783                 }
5784                 if (qualityreduction >= 2)
5785                 {
5786                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5787                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5788                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5789                 }
5790         }
5791 }
5792
5793 void R_Bloom_StartFrame(void)
5794 {
5795         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5796         int viewwidth, viewheight;
5797         textype_t textype;
5798
5799         if (r_viewscale_fpsscaling.integer)
5800         {
5801                 double actualframetime;
5802                 double targetframetime;
5803                 double adjust;
5804                 actualframetime = r_refdef.lastdrawscreentime;
5805                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5806                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5807                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5808                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5809                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5810                 viewscalefpsadjusted += adjust;
5811                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5812         }
5813         else
5814                 viewscalefpsadjusted = 1.0f;
5815
5816         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5817
5818         switch(vid.renderpath)
5819         {
5820         case RENDERPATH_GL20:
5821         case RENDERPATH_D3D9:
5822         case RENDERPATH_D3D10:
5823         case RENDERPATH_D3D11:
5824         case RENDERPATH_SOFT:
5825         case RENDERPATH_GLES2:
5826                 break;
5827         case RENDERPATH_GL11:
5828         case RENDERPATH_GL13:
5829         case RENDERPATH_GLES1:
5830                 return;
5831         }
5832
5833         // set bloomwidth and bloomheight to the bloom resolution that will be
5834         // used (often less than the screen resolution for faster rendering)
5835         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5836         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5837         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5838         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5839         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5840
5841         // calculate desired texture sizes
5842         if (vid.support.arb_texture_non_power_of_two)
5843         {
5844                 screentexturewidth = vid.width;
5845                 screentextureheight = vid.height;
5846                 bloomtexturewidth = r_bloomstate.bloomwidth;
5847                 bloomtextureheight = r_bloomstate.bloomheight;
5848         }
5849         else
5850         {
5851                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5852                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5853                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5854                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5855         }
5856
5857         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))
5858         {
5859                 Cvar_SetValueQuick(&r_hdr, 0);
5860                 Cvar_SetValueQuick(&r_bloom, 0);
5861                 Cvar_SetValueQuick(&r_motionblur, 0);
5862                 Cvar_SetValueQuick(&r_damageblur, 0);
5863         }
5864
5865         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)
5866                 screentexturewidth = screentextureheight = 0;
5867         if (!r_hdr.integer && !r_bloom.integer)
5868                 bloomtexturewidth = bloomtextureheight = 0;
5869
5870         textype = TEXTYPE_COLORBUFFER;
5871         switch (vid.renderpath)
5872         {
5873         case RENDERPATH_GL20:
5874         case RENDERPATH_GLES2:
5875                 if (vid.support.ext_framebuffer_object)
5876                 {
5877                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5878                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5879                 }
5880                 break;
5881         case RENDERPATH_GL11:
5882         case RENDERPATH_GL13:
5883         case RENDERPATH_GLES1:
5884         case RENDERPATH_D3D9:
5885         case RENDERPATH_D3D10:
5886         case RENDERPATH_D3D11:
5887         case RENDERPATH_SOFT:
5888                 break;
5889         }
5890
5891         // allocate textures as needed
5892         if (r_bloomstate.screentexturewidth != screentexturewidth
5893          || r_bloomstate.screentextureheight != screentextureheight
5894          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5895          || r_bloomstate.bloomtextureheight != bloomtextureheight
5896          || r_bloomstate.texturetype != textype
5897          || r_bloomstate.viewfbo != r_viewfbo.integer)
5898         {
5899                 if (r_bloomstate.texture_bloom)
5900                         R_FreeTexture(r_bloomstate.texture_bloom);
5901                 r_bloomstate.texture_bloom = NULL;
5902                 if (r_bloomstate.texture_screen)
5903                         R_FreeTexture(r_bloomstate.texture_screen);
5904                 r_bloomstate.texture_screen = NULL;
5905                 if (r_bloomstate.fbo_framebuffer)
5906                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5907                 r_bloomstate.fbo_framebuffer = 0;
5908                 if (r_bloomstate.texture_framebuffercolor)
5909                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5910                 r_bloomstate.texture_framebuffercolor = NULL;
5911                 if (r_bloomstate.texture_framebufferdepth)
5912                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5913                 r_bloomstate.texture_framebufferdepth = NULL;
5914                 r_bloomstate.screentexturewidth = screentexturewidth;
5915                 r_bloomstate.screentextureheight = screentextureheight;
5916                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5917                         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);
5918                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5919                 {
5920                         // FIXME: choose depth bits based on a cvar
5921                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5922                         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);
5923                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5924                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5925                         // render depth into one texture and normalmap into the other
5926                         if (qglDrawBuffer)
5927                         {
5928                                 int status;
5929                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5930                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5931                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5932                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5933                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5934                         }
5935                 }
5936                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5937                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5938                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5939                         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);
5940                 r_bloomstate.viewfbo = r_viewfbo.integer;
5941                 r_bloomstate.texturetype = textype;
5942         }
5943
5944         // when doing a reduced render (HDR) we want to use a smaller area
5945         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5946         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5947         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5948         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5949         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5950
5951         // set up a texcoord array for the full resolution screen image
5952         // (we have to keep this around to copy back during final render)
5953         r_bloomstate.screentexcoord2f[0] = 0;
5954         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5955         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5956         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5957         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5958         r_bloomstate.screentexcoord2f[5] = 0;
5959         r_bloomstate.screentexcoord2f[6] = 0;
5960         r_bloomstate.screentexcoord2f[7] = 0;
5961
5962         // set up a texcoord array for the reduced resolution bloom image
5963         // (which will be additive blended over the screen image)
5964         r_bloomstate.bloomtexcoord2f[0] = 0;
5965         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5966         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5967         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5968         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5969         r_bloomstate.bloomtexcoord2f[5] = 0;
5970         r_bloomstate.bloomtexcoord2f[6] = 0;
5971         r_bloomstate.bloomtexcoord2f[7] = 0;
5972
5973         switch(vid.renderpath)
5974         {
5975         case RENDERPATH_GL11:
5976         case RENDERPATH_GL13:
5977         case RENDERPATH_GL20:
5978         case RENDERPATH_SOFT:
5979         case RENDERPATH_GLES1:
5980         case RENDERPATH_GLES2:
5981                 break;
5982         case RENDERPATH_D3D9:
5983         case RENDERPATH_D3D10:
5984         case RENDERPATH_D3D11:
5985                 {
5986                         int i;
5987                         for (i = 0;i < 4;i++)
5988                         {
5989                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5990                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5991                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5992                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5993                         }
5994                 }
5995                 break;
5996         }
5997
5998         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5999         {
6000                 r_bloomstate.enabled = true;
6001                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6002         }
6003
6004         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);
6005
6006         if (r_bloomstate.fbo_framebuffer)
6007                 r_refdef.view.clear = true;
6008 }
6009
6010 void R_Bloom_CopyBloomTexture(float colorscale)
6011 {
6012         r_refdef.stats.bloom++;
6013
6014         // scale down screen texture to the bloom texture size
6015         CHECKGLERROR
6016         R_Mesh_SetMainRenderTargets();
6017         R_SetViewport(&r_bloomstate.viewport);
6018         GL_BlendFunc(GL_ONE, GL_ZERO);
6019         GL_Color(colorscale, colorscale, colorscale, 1);
6020         // 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...
6021         switch(vid.renderpath)
6022         {
6023         case RENDERPATH_GL11:
6024         case RENDERPATH_GL13:
6025         case RENDERPATH_GL20:
6026         case RENDERPATH_GLES1:
6027         case RENDERPATH_GLES2:
6028         case RENDERPATH_SOFT:
6029                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6030                 break;
6031         case RENDERPATH_D3D9:
6032         case RENDERPATH_D3D10:
6033         case RENDERPATH_D3D11:
6034                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6035                 break;
6036         }
6037         // TODO: do boxfilter scale-down in shader?
6038         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6039         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6040         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6041
6042         // we now have a bloom image in the framebuffer
6043         // copy it into the bloom image texture for later processing
6044         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);
6045         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6046 }
6047
6048 void R_Bloom_CopyHDRTexture(void)
6049 {
6050         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);
6051         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6052 }
6053
6054 void R_Bloom_MakeTexture(void)
6055 {
6056         int x, range, dir;
6057         float xoffset, yoffset, r, brighten;
6058
6059         r_refdef.stats.bloom++;
6060
6061         R_ResetViewRendering2D();
6062
6063         // we have a bloom image in the framebuffer
6064         CHECKGLERROR
6065         R_SetViewport(&r_bloomstate.viewport);
6066
6067         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6068         {
6069                 x *= 2;
6070                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6071                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6072                 GL_Color(r,r,r,1);
6073                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6074                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6075                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6076                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6077
6078                 // copy the vertically blurred bloom view to a texture
6079                 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);
6080                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6081         }
6082
6083         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6084         brighten = r_bloom_brighten.value;
6085         if (r_bloomstate.hdr)
6086                 brighten *= r_hdr_range.value;
6087         brighten = sqrt(brighten);
6088         if(range >= 1)
6089                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6090         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6091
6092         for (dir = 0;dir < 2;dir++)
6093         {
6094                 // blend on at multiple vertical offsets to achieve a vertical blur
6095                 // TODO: do offset blends using GLSL
6096                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6097                 GL_BlendFunc(GL_ONE, GL_ZERO);
6098                 for (x = -range;x <= range;x++)
6099                 {
6100                         if (!dir){xoffset = 0;yoffset = x;}
6101                         else {xoffset = x;yoffset = 0;}
6102                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6103                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6104                         // compute a texcoord array with the specified x and y offset
6105                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6106                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6107                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6108                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6109                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6110                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6111                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6112                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6113                         // this r value looks like a 'dot' particle, fading sharply to
6114                         // black at the edges
6115                         // (probably not realistic but looks good enough)
6116                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6117                         //r = brighten/(range*2+1);
6118                         r = brighten / (range * 2 + 1);
6119                         if(range >= 1)
6120                                 r *= (1 - x*x/(float)(range*range));
6121                         GL_Color(r, r, r, 1);
6122                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6123                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6125                         GL_BlendFunc(GL_ONE, GL_ONE);
6126                 }
6127
6128                 // copy the vertically blurred bloom view to a texture
6129                 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);
6130                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6131         }
6132 }
6133
6134 void R_HDR_RenderBloomTexture(void)
6135 {
6136         int oldwidth, oldheight;
6137         float oldcolorscale;
6138         qboolean oldwaterstate;
6139
6140         oldwaterstate = r_waterstate.enabled;
6141         oldcolorscale = r_refdef.view.colorscale;
6142         oldwidth = r_refdef.view.width;
6143         oldheight = r_refdef.view.height;
6144         r_refdef.view.width = r_bloomstate.bloomwidth;
6145         r_refdef.view.height = r_bloomstate.bloomheight;
6146
6147         if(r_hdr.integer < 2)
6148                 r_waterstate.enabled = false;
6149
6150         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6151         // TODO: add exposure compensation features
6152         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6153
6154         r_refdef.view.showdebug = false;
6155         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6156
6157         R_ResetViewRendering3D();
6158
6159         R_ClearScreen(r_refdef.fogenabled);
6160         if (r_timereport_active)
6161                 R_TimeReport("HDRclear");
6162
6163         R_View_Update();
6164         if (r_timereport_active)
6165                 R_TimeReport("visibility");
6166
6167         // only do secondary renders with HDR if r_hdr is 2 or higher
6168         r_waterstate.numwaterplanes = 0;
6169         if (r_waterstate.enabled)
6170                 R_RenderWaterPlanes();
6171
6172         r_refdef.view.showdebug = true;
6173         R_RenderScene();
6174         r_waterstate.numwaterplanes = 0;
6175
6176         R_ResetViewRendering2D();
6177
6178         R_Bloom_CopyHDRTexture();
6179         R_Bloom_MakeTexture();
6180
6181         // restore the view settings
6182         r_waterstate.enabled = oldwaterstate;
6183         r_refdef.view.width = oldwidth;
6184         r_refdef.view.height = oldheight;
6185         r_refdef.view.colorscale = oldcolorscale;
6186
6187         R_ResetViewRendering3D();
6188
6189         R_ClearScreen(r_refdef.fogenabled);
6190         if (r_timereport_active)
6191                 R_TimeReport("viewclear");
6192 }
6193
6194 static void R_BlendView(void)
6195 {
6196         unsigned int permutation;
6197         float uservecs[4][4];
6198
6199         switch (vid.renderpath)
6200         {
6201         case RENDERPATH_GL20:
6202         case RENDERPATH_D3D9:
6203         case RENDERPATH_D3D10:
6204         case RENDERPATH_D3D11:
6205         case RENDERPATH_SOFT:
6206         case RENDERPATH_GLES2:
6207                 permutation =
6208                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6209                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6210                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6211                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6212                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6213
6214                 if (r_bloomstate.texture_screen)
6215                 {
6216                         // make sure the buffer is available
6217                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6218
6219                         R_ResetViewRendering2D();
6220                         R_Mesh_SetMainRenderTargets();
6221
6222                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6223                         {
6224                                 // declare variables
6225                                 float speed;
6226                                 static float avgspeed;
6227
6228                                 speed = VectorLength(cl.movement_velocity);
6229
6230                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6231                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6232
6233                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6234                                 speed = bound(0, speed, 1);
6235                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6236
6237                                 // calculate values into a standard alpha
6238                                 cl.motionbluralpha = 1 - exp(-
6239                                                 (
6240                                                  (r_motionblur.value * speed / 80)
6241                                                  +
6242                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6243                                                 )
6244                                                 /
6245                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6246                                            );
6247
6248                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6249                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6250                                 // apply the blur
6251                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6252                                 {
6253                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6254                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6255                                         switch(vid.renderpath)
6256                                         {
6257                                         case RENDERPATH_GL11:
6258                                         case RENDERPATH_GL13:
6259                                         case RENDERPATH_GL20:
6260                                         case RENDERPATH_GLES1:
6261                                         case RENDERPATH_GLES2:
6262                                         case RENDERPATH_SOFT:
6263                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6264                                                 break;
6265                                         case RENDERPATH_D3D9:
6266                                         case RENDERPATH_D3D10:
6267                                         case RENDERPATH_D3D11:
6268                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6269                                                 break;
6270                                         }
6271                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6272                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6273                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6274                                 }
6275                         }
6276
6277                         // copy view into the screen texture
6278                         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);
6279                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6280                 }
6281                 else if (!r_bloomstate.texture_bloom)
6282                 {
6283                         // we may still have to do view tint...
6284                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6285                         {
6286                                 // apply a color tint to the whole view
6287                                 R_ResetViewRendering2D();
6288                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6289                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6290                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6291                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6292                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6293                         }
6294                         break; // no screen processing, no bloom, skip it
6295                 }
6296
6297                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6298                 {
6299                         // render simple bloom effect
6300                         // copy the screen and shrink it and darken it for the bloom process
6301                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6302                         // make the bloom texture
6303                         R_Bloom_MakeTexture();
6304                 }
6305
6306 #if _MSC_VER >= 1400
6307 #define sscanf sscanf_s
6308 #endif
6309                 memset(uservecs, 0, sizeof(uservecs));
6310                 if (r_glsl_postprocess_uservec1_enable.integer)
6311                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6312                 if (r_glsl_postprocess_uservec2_enable.integer)
6313                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6314                 if (r_glsl_postprocess_uservec3_enable.integer)
6315                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6316                 if (r_glsl_postprocess_uservec4_enable.integer)
6317                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6318
6319                 R_ResetViewRendering2D();
6320                 GL_Color(1, 1, 1, 1);
6321                 GL_BlendFunc(GL_ONE, GL_ZERO);
6322
6323                 switch(vid.renderpath)
6324                 {
6325                 case RENDERPATH_GL20:
6326                 case RENDERPATH_GLES2:
6327                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6328                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6329                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6330                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6331                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6332                         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]);
6333                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6334                         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]);
6335                         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]);
6336                         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]);
6337                         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]);
6338                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6339                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6340                         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);
6341                         break;
6342                 case RENDERPATH_D3D9:
6343 #ifdef SUPPORTD3D
6344                         // 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...
6345                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6346                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6347                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6348                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6349                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6350                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6351                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6352                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6353                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6354                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6355                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6356                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6357                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6358                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6359 #endif
6360                         break;
6361                 case RENDERPATH_D3D10:
6362                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6363                         break;
6364                 case RENDERPATH_D3D11:
6365                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6366                         break;
6367                 case RENDERPATH_SOFT:
6368                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6369                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6370                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6371                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6372                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6373                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6374                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6375                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6376                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6377                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6378                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6379                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6380                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6381                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6382                         break;
6383                 default:
6384                         break;
6385                 }
6386                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6387                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6388                 break;
6389         case RENDERPATH_GL11:
6390         case RENDERPATH_GL13:
6391         case RENDERPATH_GLES1:
6392                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6393                 {
6394                         // apply a color tint to the whole view
6395                         R_ResetViewRendering2D();
6396                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6397                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6398                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6399                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6400                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6401                 }
6402                 break;
6403         }
6404 }
6405
6406 matrix4x4_t r_waterscrollmatrix;
6407
6408 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6409 {
6410         if (r_refdef.fog_density)
6411         {
6412                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6413                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6414                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6415
6416                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6417                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6418                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6419                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6420
6421                 {
6422                         vec3_t fogvec;
6423                         VectorCopy(r_refdef.fogcolor, fogvec);
6424                         //   color.rgb *= ContrastBoost * SceneBrightness;
6425                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6426                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6427                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6428                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6429                 }
6430         }
6431 }
6432
6433 void R_UpdateVariables(void)
6434 {
6435         R_Textures_Frame();
6436
6437         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6438
6439         r_refdef.farclip = r_farclip_base.value;
6440         if (r_refdef.scene.worldmodel)
6441                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6442         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6443
6444         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6445                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6446         r_refdef.polygonfactor = 0;
6447         r_refdef.polygonoffset = 0;
6448         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6449         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6450
6451         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6452         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6453         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6454         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6455         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6456         if (FAKELIGHT_ENABLED)
6457         {
6458                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6459         }
6460         if (r_showsurfaces.integer)
6461         {
6462                 r_refdef.scene.rtworld = false;
6463                 r_refdef.scene.rtworldshadows = false;
6464                 r_refdef.scene.rtdlight = false;
6465                 r_refdef.scene.rtdlightshadows = false;
6466                 r_refdef.lightmapintensity = 0;
6467         }
6468
6469         if (gamemode == GAME_NEHAHRA)
6470         {
6471                 if (gl_fogenable.integer)
6472                 {
6473                         r_refdef.oldgl_fogenable = true;
6474                         r_refdef.fog_density = gl_fogdensity.value;
6475                         r_refdef.fog_red = gl_fogred.value;
6476                         r_refdef.fog_green = gl_foggreen.value;
6477                         r_refdef.fog_blue = gl_fogblue.value;
6478                         r_refdef.fog_alpha = 1;
6479                         r_refdef.fog_start = 0;
6480                         r_refdef.fog_end = gl_skyclip.value;
6481                         r_refdef.fog_height = 1<<30;
6482                         r_refdef.fog_fadedepth = 128;
6483                 }
6484                 else if (r_refdef.oldgl_fogenable)
6485                 {
6486                         r_refdef.oldgl_fogenable = false;
6487                         r_refdef.fog_density = 0;
6488                         r_refdef.fog_red = 0;
6489                         r_refdef.fog_green = 0;
6490                         r_refdef.fog_blue = 0;
6491                         r_refdef.fog_alpha = 0;
6492                         r_refdef.fog_start = 0;
6493                         r_refdef.fog_end = 0;
6494                         r_refdef.fog_height = 1<<30;
6495                         r_refdef.fog_fadedepth = 128;
6496                 }
6497         }
6498
6499         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6500         r_refdef.fog_start = max(0, r_refdef.fog_start);
6501         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6502
6503         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6504
6505         if (r_refdef.fog_density && r_drawfog.integer)
6506         {
6507                 r_refdef.fogenabled = true;
6508                 // this is the point where the fog reaches 0.9986 alpha, which we
6509                 // consider a good enough cutoff point for the texture
6510                 // (0.9986 * 256 == 255.6)
6511                 if (r_fog_exp2.integer)
6512                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6513                 else
6514                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6515                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6516                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6517                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6518                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6519                         R_BuildFogHeightTexture();
6520                 // fog color was already set
6521                 // update the fog texture
6522                 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)
6523                         R_BuildFogTexture();
6524                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6525                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6526         }
6527         else
6528                 r_refdef.fogenabled = false;
6529
6530         switch(vid.renderpath)
6531         {
6532         case RENDERPATH_GL20:
6533         case RENDERPATH_D3D9:
6534         case RENDERPATH_D3D10:
6535         case RENDERPATH_D3D11:
6536         case RENDERPATH_SOFT:
6537         case RENDERPATH_GLES2:
6538                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6539                 {
6540                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6541                         {
6542                                 // build GLSL gamma texture
6543 #define RAMPWIDTH 256
6544                                 unsigned short ramp[RAMPWIDTH * 3];
6545                                 unsigned char rampbgr[RAMPWIDTH][4];
6546                                 int i;
6547
6548                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6549
6550                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6551                                 for(i = 0; i < RAMPWIDTH; ++i)
6552                                 {
6553                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6554                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6555                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6556                                         rampbgr[i][3] = 0;
6557                                 }
6558                                 if (r_texture_gammaramps)
6559                                 {
6560                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6561                                 }
6562                                 else
6563                                 {
6564                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6565                                 }
6566                         }
6567                 }
6568                 else
6569                 {
6570                         // remove GLSL gamma texture
6571                 }
6572                 break;
6573         case RENDERPATH_GL11:
6574         case RENDERPATH_GL13:
6575         case RENDERPATH_GLES1:
6576                 break;
6577         }
6578 }
6579
6580 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6581 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6582 /*
6583 ================
6584 R_SelectScene
6585 ================
6586 */
6587 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6588         if( scenetype != r_currentscenetype ) {
6589                 // store the old scenetype
6590                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6591                 r_currentscenetype = scenetype;
6592                 // move in the new scene
6593                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6594         }
6595 }
6596
6597 /*
6598 ================
6599 R_GetScenePointer
6600 ================
6601 */
6602 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6603 {
6604         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6605         if( scenetype == r_currentscenetype ) {
6606                 return &r_refdef.scene;
6607         } else {
6608                 return &r_scenes_store[ scenetype ];
6609         }
6610 }
6611
6612 /*
6613 ================
6614 R_RenderView
6615 ================
6616 */
6617 int dpsoftrast_test;
6618 void R_RenderView(void)
6619 {
6620         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6621
6622         dpsoftrast_test = r_test.integer;
6623
6624         if (r_timereport_active)
6625                 R_TimeReport("start");
6626         r_textureframe++; // used only by R_GetCurrentTexture
6627         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6628
6629         if(R_CompileShader_CheckStaticParms())
6630                 R_GLSL_Restart_f();
6631
6632         if (!r_drawentities.integer)
6633                 r_refdef.scene.numentities = 0;
6634
6635         R_AnimCache_ClearCache();
6636         R_FrameData_NewFrame();
6637
6638         /* adjust for stereo display */
6639         if(R_Stereo_Active())
6640         {
6641                 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);
6642                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6643         }
6644
6645         if (r_refdef.view.isoverlay)
6646         {
6647                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6648                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6649                 R_TimeReport("depthclear");
6650
6651                 r_refdef.view.showdebug = false;
6652
6653                 r_waterstate.enabled = false;
6654                 r_waterstate.numwaterplanes = 0;
6655
6656                 R_RenderScene();
6657
6658                 r_refdef.view.matrix = originalmatrix;
6659
6660                 CHECKGLERROR
6661                 return;
6662         }
6663
6664         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6665         {
6666                 r_refdef.view.matrix = originalmatrix;
6667                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6668         }
6669
6670         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6671
6672         R_RenderView_UpdateViewVectors();
6673
6674         R_Shadow_UpdateWorldLightSelection();
6675
6676         R_Bloom_StartFrame();
6677         R_Water_StartFrame();
6678
6679         CHECKGLERROR
6680         if (r_timereport_active)
6681                 R_TimeReport("viewsetup");
6682
6683         R_ResetViewRendering3D();
6684
6685         if (r_refdef.view.clear || r_refdef.fogenabled)
6686         {
6687                 R_ClearScreen(r_refdef.fogenabled);
6688                 if (r_timereport_active)
6689                         R_TimeReport("viewclear");
6690         }
6691         r_refdef.view.clear = true;
6692
6693         // this produces a bloom texture to be used in R_BlendView() later
6694         if (r_bloomstate.hdr)
6695         {
6696                 R_HDR_RenderBloomTexture();
6697                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6698                 r_textureframe++; // used only by R_GetCurrentTexture
6699         }
6700
6701         r_refdef.view.showdebug = true;
6702
6703         R_View_Update();
6704         if (r_timereport_active)
6705                 R_TimeReport("visibility");
6706
6707         r_waterstate.numwaterplanes = 0;
6708         if (r_waterstate.enabled)
6709                 R_RenderWaterPlanes();
6710
6711         R_RenderScene();
6712         r_waterstate.numwaterplanes = 0;
6713
6714         R_BlendView();
6715         if (r_timereport_active)
6716                 R_TimeReport("blendview");
6717
6718         GL_Scissor(0, 0, vid.width, vid.height);
6719         GL_ScissorTest(false);
6720
6721         r_refdef.view.matrix = originalmatrix;
6722
6723         CHECKGLERROR
6724 }
6725
6726 void R_RenderWaterPlanes(void)
6727 {
6728         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6729         {
6730                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6731                 if (r_timereport_active)
6732                         R_TimeReport("waterworld");
6733         }
6734
6735         // don't let sound skip if going slow
6736         if (r_refdef.scene.extraupdate)
6737                 S_ExtraUpdate ();
6738
6739         R_DrawModelsAddWaterPlanes();
6740         if (r_timereport_active)
6741                 R_TimeReport("watermodels");
6742
6743         if (r_waterstate.numwaterplanes)
6744         {
6745                 R_Water_ProcessPlanes();
6746                 if (r_timereport_active)
6747                         R_TimeReport("waterscenes");
6748         }
6749 }
6750
6751 extern void R_DrawLightningBeams (void);
6752 extern void VM_CL_AddPolygonsToMeshQueue (void);
6753 extern void R_DrawPortals (void);
6754 extern cvar_t cl_locs_show;
6755 static void R_DrawLocs(void);
6756 static void R_DrawEntityBBoxes(void);
6757 static void R_DrawModelDecals(void);
6758 extern void R_DrawModelShadows(void);
6759 extern void R_DrawModelShadowMaps(void);
6760 extern cvar_t cl_decals_newsystem;
6761 extern qboolean r_shadow_usingdeferredprepass;
6762 void R_RenderScene(void)
6763 {
6764         qboolean shadowmapping = false;
6765
6766         if (r_timereport_active)
6767                 R_TimeReport("beginscene");
6768
6769         r_refdef.stats.renders++;
6770
6771         R_UpdateFogColor();
6772
6773         // don't let sound skip if going slow
6774         if (r_refdef.scene.extraupdate)
6775                 S_ExtraUpdate ();
6776
6777         R_MeshQueue_BeginScene();
6778
6779         R_SkyStartFrame();
6780
6781         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);
6782
6783         if (r_timereport_active)
6784                 R_TimeReport("skystartframe");
6785
6786         if (cl.csqc_vidvars.drawworld)
6787         {
6788                 // don't let sound skip if going slow
6789                 if (r_refdef.scene.extraupdate)
6790                         S_ExtraUpdate ();
6791
6792                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6793                 {
6794                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6795                         if (r_timereport_active)
6796                                 R_TimeReport("worldsky");
6797                 }
6798
6799                 if (R_DrawBrushModelsSky() && r_timereport_active)
6800                         R_TimeReport("bmodelsky");
6801
6802                 if (skyrendermasked && skyrenderlater)
6803                 {
6804                         // we have to force off the water clipping plane while rendering sky
6805                         R_SetupView(false);
6806                         R_Sky();
6807                         R_SetupView(true);
6808                         if (r_timereport_active)
6809                                 R_TimeReport("sky");
6810                 }
6811         }
6812
6813         R_AnimCache_CacheVisibleEntities();
6814         if (r_timereport_active)
6815                 R_TimeReport("animation");
6816
6817         R_Shadow_PrepareLights();
6818         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6819                 R_Shadow_PrepareModelShadows();
6820         if (r_timereport_active)
6821                 R_TimeReport("preparelights");
6822
6823         if (R_Shadow_ShadowMappingEnabled())
6824                 shadowmapping = true;
6825
6826         if (r_shadow_usingdeferredprepass)
6827                 R_Shadow_DrawPrepass();
6828
6829         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6830         {
6831                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6832                 if (r_timereport_active)
6833                         R_TimeReport("worlddepth");
6834         }
6835         if (r_depthfirst.integer >= 2)
6836         {
6837                 R_DrawModelsDepth();
6838                 if (r_timereport_active)
6839                         R_TimeReport("modeldepth");
6840         }
6841
6842         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6843         {
6844                 R_DrawModelShadowMaps();
6845                 R_ResetViewRendering3D();
6846                 // don't let sound skip if going slow
6847                 if (r_refdef.scene.extraupdate)
6848                         S_ExtraUpdate ();
6849         }
6850
6851         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6852         {
6853                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6854                 if (r_timereport_active)
6855                         R_TimeReport("world");
6856         }
6857
6858         // don't let sound skip if going slow
6859         if (r_refdef.scene.extraupdate)
6860                 S_ExtraUpdate ();
6861
6862         R_DrawModels();
6863         if (r_timereport_active)
6864                 R_TimeReport("models");
6865
6866         // don't let sound skip if going slow
6867         if (r_refdef.scene.extraupdate)
6868                 S_ExtraUpdate ();
6869
6870         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6871         {
6872                 R_DrawModelShadows();
6873                 R_ResetViewRendering3D();
6874                 // don't let sound skip if going slow
6875                 if (r_refdef.scene.extraupdate)
6876                         S_ExtraUpdate ();
6877         }
6878
6879         if (!r_shadow_usingdeferredprepass)
6880         {
6881                 R_Shadow_DrawLights();
6882                 if (r_timereport_active)
6883                         R_TimeReport("rtlights");
6884         }
6885
6886         // don't let sound skip if going slow
6887         if (r_refdef.scene.extraupdate)
6888                 S_ExtraUpdate ();
6889
6890         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6891         {
6892                 R_DrawModelShadows();
6893                 R_ResetViewRendering3D();
6894                 // don't let sound skip if going slow
6895                 if (r_refdef.scene.extraupdate)
6896                         S_ExtraUpdate ();
6897         }
6898
6899         if (cl.csqc_vidvars.drawworld)
6900         {
6901                 if (cl_decals_newsystem.integer)
6902                 {
6903                         R_DrawModelDecals();
6904                         if (r_timereport_active)
6905                                 R_TimeReport("modeldecals");
6906                 }
6907                 else
6908                 {
6909                         R_DrawDecals();
6910                         if (r_timereport_active)
6911                                 R_TimeReport("decals");
6912                 }
6913
6914                 R_DrawParticles();
6915                 if (r_timereport_active)
6916                         R_TimeReport("particles");
6917
6918                 R_DrawExplosions();
6919                 if (r_timereport_active)
6920                         R_TimeReport("explosions");
6921
6922                 R_DrawLightningBeams();
6923                 if (r_timereport_active)
6924                         R_TimeReport("lightning");
6925         }
6926
6927         VM_CL_AddPolygonsToMeshQueue();
6928
6929         if (r_refdef.view.showdebug)
6930         {
6931                 if (cl_locs_show.integer)
6932                 {
6933                         R_DrawLocs();
6934                         if (r_timereport_active)
6935                                 R_TimeReport("showlocs");
6936                 }
6937
6938                 if (r_drawportals.integer)
6939                 {
6940                         R_DrawPortals();
6941                         if (r_timereport_active)
6942                                 R_TimeReport("portals");
6943                 }
6944
6945                 if (r_showbboxes.value > 0)
6946                 {
6947                         R_DrawEntityBBoxes();
6948                         if (r_timereport_active)
6949                                 R_TimeReport("bboxes");
6950                 }
6951         }
6952
6953         if (r_transparent.integer)
6954         {
6955                 R_MeshQueue_RenderTransparent();
6956                 if (r_timereport_active)
6957                         R_TimeReport("drawtrans");
6958         }
6959
6960         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))
6961         {
6962                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6963                 if (r_timereport_active)
6964                         R_TimeReport("worlddebug");
6965                 R_DrawModelsDebug();
6966                 if (r_timereport_active)
6967                         R_TimeReport("modeldebug");
6968         }
6969
6970         if (cl.csqc_vidvars.drawworld)
6971         {
6972                 R_Shadow_DrawCoronas();
6973                 if (r_timereport_active)
6974                         R_TimeReport("coronas");
6975         }
6976
6977 #if 0
6978         {
6979                 GL_DepthTest(false);
6980                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6981                 GL_Color(1, 1, 1, 1);
6982                 qglBegin(GL_POLYGON);
6983                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6984                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6985                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6986                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6987                 qglEnd();
6988                 qglBegin(GL_POLYGON);
6989                 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]);
6990                 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]);
6991                 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]);
6992                 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]);
6993                 qglEnd();
6994                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6995         }
6996 #endif
6997
6998         // don't let sound skip if going slow
6999         if (r_refdef.scene.extraupdate)
7000                 S_ExtraUpdate ();
7001
7002         R_ResetViewRendering2D();
7003 }
7004
7005 static const unsigned short bboxelements[36] =
7006 {
7007         5, 1, 3, 5, 3, 7,
7008         6, 2, 0, 6, 0, 4,
7009         7, 3, 2, 7, 2, 6,
7010         4, 0, 1, 4, 1, 5,
7011         4, 5, 7, 4, 7, 6,
7012         1, 0, 2, 1, 2, 3,
7013 };
7014
7015 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7016 {
7017         int i;
7018         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7019
7020         RSurf_ActiveWorldEntity();
7021
7022         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7023         GL_DepthMask(false);
7024         GL_DepthRange(0, 1);
7025         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7026 //      R_Mesh_ResetTextureState();
7027
7028         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7029         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7030         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7031         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7032         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7033         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7034         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7035         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7036         R_FillColors(color4f, 8, cr, cg, cb, ca);
7037         if (r_refdef.fogenabled)
7038         {
7039                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7040                 {
7041                         f1 = RSurf_FogVertex(v);
7042                         f2 = 1 - f1;
7043                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7044                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7045                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7046                 }
7047         }
7048         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7049         R_Mesh_ResetTextureState();
7050         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7051         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7052 }
7053
7054 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7055 {
7056         int i;
7057         float color[4];
7058         prvm_edict_t *edict;
7059         prvm_prog_t *prog_save = prog;
7060
7061         // this function draws bounding boxes of server entities
7062         if (!sv.active)
7063                 return;
7064
7065         GL_CullFace(GL_NONE);
7066         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7067
7068         prog = 0;
7069         SV_VM_Begin();
7070         for (i = 0;i < numsurfaces;i++)
7071         {
7072                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7073                 switch ((int)edict->fields.server->solid)
7074                 {
7075                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7076                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7077                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7078                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7079                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7080                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7081                 }
7082                 color[3] *= r_showbboxes.value;
7083                 color[3] = bound(0, color[3], 1);
7084                 GL_DepthTest(!r_showdisabledepthtest.integer);
7085                 GL_CullFace(r_refdef.view.cullface_front);
7086                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7087         }
7088         SV_VM_End();
7089         prog = prog_save;
7090 }
7091
7092 static void R_DrawEntityBBoxes(void)
7093 {
7094         int i;
7095         prvm_edict_t *edict;
7096         vec3_t center;
7097         prvm_prog_t *prog_save = prog;
7098
7099         // this function draws bounding boxes of server entities
7100         if (!sv.active)
7101                 return;
7102
7103         prog = 0;
7104         SV_VM_Begin();
7105         for (i = 0;i < prog->num_edicts;i++)
7106         {
7107                 edict = PRVM_EDICT_NUM(i);
7108                 if (edict->priv.server->free)
7109                         continue;
7110                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7111                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7112                         continue;
7113                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7114                         continue;
7115                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7116                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7117         }
7118         SV_VM_End();
7119         prog = prog_save;
7120 }
7121
7122 static const int nomodelelement3i[24] =
7123 {
7124         5, 2, 0,
7125         5, 1, 2,
7126         5, 0, 3,
7127         5, 3, 1,
7128         0, 2, 4,
7129         2, 1, 4,
7130         3, 0, 4,
7131         1, 3, 4
7132 };
7133
7134 static const unsigned short nomodelelement3s[24] =
7135 {
7136         5, 2, 0,
7137         5, 1, 2,
7138         5, 0, 3,
7139         5, 3, 1,
7140         0, 2, 4,
7141         2, 1, 4,
7142         3, 0, 4,
7143         1, 3, 4
7144 };
7145
7146 static const float nomodelvertex3f[6*3] =
7147 {
7148         -16,   0,   0,
7149          16,   0,   0,
7150           0, -16,   0,
7151           0,  16,   0,
7152           0,   0, -16,
7153           0,   0,  16
7154 };
7155
7156 static const float nomodelcolor4f[6*4] =
7157 {
7158         0.0f, 0.0f, 0.5f, 1.0f,
7159         0.0f, 0.0f, 0.5f, 1.0f,
7160         0.0f, 0.5f, 0.0f, 1.0f,
7161         0.0f, 0.5f, 0.0f, 1.0f,
7162         0.5f, 0.0f, 0.0f, 1.0f,
7163         0.5f, 0.0f, 0.0f, 1.0f
7164 };
7165
7166 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7167 {
7168         int i;
7169         float f1, f2, *c;
7170         float color4f[6*4];
7171
7172         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);
7173
7174         // this is only called once per entity so numsurfaces is always 1, and
7175         // surfacelist is always {0}, so this code does not handle batches
7176
7177         if (rsurface.ent_flags & RENDER_ADDITIVE)
7178         {
7179                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7180                 GL_DepthMask(false);
7181         }
7182         else if (rsurface.colormod[3] < 1)
7183         {
7184                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7185                 GL_DepthMask(false);
7186         }
7187         else
7188         {
7189                 GL_BlendFunc(GL_ONE, GL_ZERO);
7190                 GL_DepthMask(true);
7191         }
7192         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7193         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7194         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7195         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7196         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7197         for (i = 0, c = color4f;i < 6;i++, c += 4)
7198         {
7199                 c[0] *= rsurface.colormod[0];
7200                 c[1] *= rsurface.colormod[1];
7201                 c[2] *= rsurface.colormod[2];
7202                 c[3] *= rsurface.colormod[3];
7203         }
7204         if (r_refdef.fogenabled)
7205         {
7206                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7207                 {
7208                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7209                         f2 = 1 - f1;
7210                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7211                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7212                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7213                 }
7214         }
7215 //      R_Mesh_ResetTextureState();
7216         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7217         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7218         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7219 }
7220
7221 void R_DrawNoModel(entity_render_t *ent)
7222 {
7223         vec3_t org;
7224         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7225         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7226                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7227         else
7228                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7229 }
7230
7231 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7232 {
7233         vec3_t right1, right2, diff, normal;
7234
7235         VectorSubtract (org2, org1, normal);
7236
7237         // calculate 'right' vector for start
7238         VectorSubtract (r_refdef.view.origin, org1, diff);
7239         CrossProduct (normal, diff, right1);
7240         VectorNormalize (right1);
7241
7242         // calculate 'right' vector for end
7243         VectorSubtract (r_refdef.view.origin, org2, diff);
7244         CrossProduct (normal, diff, right2);
7245         VectorNormalize (right2);
7246
7247         vert[ 0] = org1[0] + width * right1[0];
7248         vert[ 1] = org1[1] + width * right1[1];
7249         vert[ 2] = org1[2] + width * right1[2];
7250         vert[ 3] = org1[0] - width * right1[0];
7251         vert[ 4] = org1[1] - width * right1[1];
7252         vert[ 5] = org1[2] - width * right1[2];
7253         vert[ 6] = org2[0] - width * right2[0];
7254         vert[ 7] = org2[1] - width * right2[1];
7255         vert[ 8] = org2[2] - width * right2[2];
7256         vert[ 9] = org2[0] + width * right2[0];
7257         vert[10] = org2[1] + width * right2[1];
7258         vert[11] = org2[2] + width * right2[2];
7259 }
7260
7261 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)
7262 {
7263         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7264         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7265         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7266         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7267         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7268         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7269         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7270         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7271         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7272         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7273         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7274         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7275 }
7276
7277 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7278 {
7279         int i;
7280         float *vertex3f;
7281         float v[3];
7282         VectorSet(v, x, y, z);
7283         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7284                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7285                         break;
7286         if (i == mesh->numvertices)
7287         {
7288                 if (mesh->numvertices < mesh->maxvertices)
7289                 {
7290                         VectorCopy(v, vertex3f);
7291                         mesh->numvertices++;
7292                 }
7293                 return mesh->numvertices;
7294         }
7295         else
7296                 return i;
7297 }
7298
7299 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7300 {
7301         int i;
7302         int *e, element[3];
7303         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7304         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7305         e = mesh->element3i + mesh->numtriangles * 3;
7306         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7307         {
7308                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7309                 if (mesh->numtriangles < mesh->maxtriangles)
7310                 {
7311                         *e++ = element[0];
7312                         *e++ = element[1];
7313                         *e++ = element[2];
7314                         mesh->numtriangles++;
7315                 }
7316                 element[1] = element[2];
7317         }
7318 }
7319
7320 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7321 {
7322         int i;
7323         int *e, element[3];
7324         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7325         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7326         e = mesh->element3i + mesh->numtriangles * 3;
7327         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7328         {
7329                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7330                 if (mesh->numtriangles < mesh->maxtriangles)
7331                 {
7332                         *e++ = element[0];
7333                         *e++ = element[1];
7334                         *e++ = element[2];
7335                         mesh->numtriangles++;
7336                 }
7337                 element[1] = element[2];
7338         }
7339 }
7340
7341 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7342 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7343 {
7344         int planenum, planenum2;
7345         int w;
7346         int tempnumpoints;
7347         mplane_t *plane, *plane2;
7348         double maxdist;
7349         double temppoints[2][256*3];
7350         // figure out how large a bounding box we need to properly compute this brush
7351         maxdist = 0;
7352         for (w = 0;w < numplanes;w++)
7353                 maxdist = max(maxdist, fabs(planes[w].dist));
7354         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7355         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7356         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7357         {
7358                 w = 0;
7359                 tempnumpoints = 4;
7360                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7361                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7362                 {
7363                         if (planenum2 == planenum)
7364                                 continue;
7365                         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);
7366                         w = !w;
7367                 }
7368                 if (tempnumpoints < 3)
7369                         continue;
7370                 // generate elements forming a triangle fan for this polygon
7371                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7372         }
7373 }
7374
7375 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)
7376 {
7377         texturelayer_t *layer;
7378         layer = t->currentlayers + t->currentnumlayers++;
7379         layer->type = type;
7380         layer->depthmask = depthmask;
7381         layer->blendfunc1 = blendfunc1;
7382         layer->blendfunc2 = blendfunc2;
7383         layer->texture = texture;
7384         layer->texmatrix = *matrix;
7385         layer->color[0] = r;
7386         layer->color[1] = g;
7387         layer->color[2] = b;
7388         layer->color[3] = a;
7389 }
7390
7391 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7392 {
7393         if(parms[0] == 0 && parms[1] == 0)
7394                 return false;
7395         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7396                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7397                         return false;
7398         return true;
7399 }
7400
7401 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7402 {
7403         double index, f;
7404         index = parms[2] + r_refdef.scene.time * parms[3];
7405         index -= floor(index);
7406         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7407         {
7408         default:
7409         case Q3WAVEFUNC_NONE:
7410         case Q3WAVEFUNC_NOISE:
7411         case Q3WAVEFUNC_COUNT:
7412                 f = 0;
7413                 break;
7414         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7415         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7416         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7417         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7418         case Q3WAVEFUNC_TRIANGLE:
7419                 index *= 4;
7420                 f = index - floor(index);
7421                 if (index < 1)
7422                         f = f;
7423                 else if (index < 2)
7424                         f = 1 - f;
7425                 else if (index < 3)
7426                         f = -f;
7427                 else
7428                         f = -(1 - f);
7429                 break;
7430         }
7431         f = parms[0] + parms[1] * f;
7432         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7433                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7434         return (float) f;
7435 }
7436
7437 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7438 {
7439         int w, h, idx;
7440         float f;
7441         float tcmat[12];
7442         matrix4x4_t matrix, temp;
7443         switch(tcmod->tcmod)
7444         {
7445                 case Q3TCMOD_COUNT:
7446                 case Q3TCMOD_NONE:
7447                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7448                                 matrix = r_waterscrollmatrix;
7449                         else
7450                                 matrix = identitymatrix;
7451                         break;
7452                 case Q3TCMOD_ENTITYTRANSLATE:
7453                         // this is used in Q3 to allow the gamecode to control texcoord
7454                         // scrolling on the entity, which is not supported in darkplaces yet.
7455                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7456                         break;
7457                 case Q3TCMOD_ROTATE:
7458                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7459                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7460                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7461                         break;
7462                 case Q3TCMOD_SCALE:
7463                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7464                         break;
7465                 case Q3TCMOD_SCROLL:
7466                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7467                         break;
7468                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7469                         w = (int) tcmod->parms[0];
7470                         h = (int) tcmod->parms[1];
7471                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7472                         f = f - floor(f);
7473                         idx = (int) floor(f * w * h);
7474                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7475                         break;
7476                 case Q3TCMOD_STRETCH:
7477                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7478                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7479                         break;
7480                 case Q3TCMOD_TRANSFORM:
7481                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7482                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7483                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7484                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7485                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7486                         break;
7487                 case Q3TCMOD_TURBULENT:
7488                         // this is handled in the RSurf_PrepareVertices function
7489                         matrix = identitymatrix;
7490                         break;
7491         }
7492         temp = *texmatrix;
7493         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7494 }
7495
7496 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7497 {
7498         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7499         char name[MAX_QPATH];
7500         skinframe_t *skinframe;
7501         unsigned char pixels[296*194];
7502         strlcpy(cache->name, skinname, sizeof(cache->name));
7503         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7504         if (developer_loading.integer)
7505                 Con_Printf("loading %s\n", name);
7506         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7507         if (!skinframe || !skinframe->base)
7508         {
7509                 unsigned char *f;
7510                 fs_offset_t filesize;
7511                 skinframe = NULL;
7512                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7513                 if (f)
7514                 {
7515                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7516                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7517                         Mem_Free(f);
7518                 }
7519         }
7520         cache->skinframe = skinframe;
7521 }
7522
7523 texture_t *R_GetCurrentTexture(texture_t *t)
7524 {
7525         int i;
7526         const entity_render_t *ent = rsurface.entity;
7527         dp_model_t *model = ent->model;
7528         q3shaderinfo_layer_tcmod_t *tcmod;
7529
7530         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7531                 return t->currentframe;
7532         t->update_lastrenderframe = r_textureframe;
7533         t->update_lastrenderentity = (void *)ent;
7534
7535         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7536                 t->camera_entity = ent->entitynumber;
7537         else
7538                 t->camera_entity = 0;
7539
7540         // switch to an alternate material if this is a q1bsp animated material
7541         {
7542                 texture_t *texture = t;
7543                 int s = rsurface.ent_skinnum;
7544                 if ((unsigned int)s >= (unsigned int)model->numskins)
7545                         s = 0;
7546                 if (model->skinscenes)
7547                 {
7548                         if (model->skinscenes[s].framecount > 1)
7549                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7550                         else
7551                                 s = model->skinscenes[s].firstframe;
7552                 }
7553                 if (s > 0)
7554                         t = t + s * model->num_surfaces;
7555                 if (t->animated)
7556                 {
7557                         // use an alternate animation if the entity's frame is not 0,
7558                         // and only if the texture has an alternate animation
7559                         if (rsurface.ent_alttextures && t->anim_total[1])
7560                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7561                         else
7562                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7563                 }
7564                 texture->currentframe = t;
7565         }
7566
7567         // update currentskinframe to be a qw skin or animation frame
7568         if (rsurface.ent_qwskin >= 0)
7569         {
7570                 i = rsurface.ent_qwskin;
7571                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7572                 {
7573                         r_qwskincache_size = cl.maxclients;
7574                         if (r_qwskincache)
7575                                 Mem_Free(r_qwskincache);
7576                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7577                 }
7578                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7579                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7580                 t->currentskinframe = r_qwskincache[i].skinframe;
7581                 if (t->currentskinframe == NULL)
7582                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7583         }
7584         else if (t->numskinframes >= 2)
7585                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7586         if (t->backgroundnumskinframes >= 2)
7587                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7588
7589         t->currentmaterialflags = t->basematerialflags;
7590         t->currentalpha = rsurface.colormod[3];
7591         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7592                 t->currentalpha *= r_wateralpha.value;
7593         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7594                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7595         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7596                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7597         if (!(rsurface.ent_flags & RENDER_LIGHT))
7598                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7599         else if (FAKELIGHT_ENABLED)
7600         {
7601                 // no modellight if using fakelight for the map
7602         }
7603         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7604         {
7605                 // pick a model lighting mode
7606                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7607                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7608                 else
7609                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7610         }
7611         if (rsurface.ent_flags & RENDER_ADDITIVE)
7612                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7613         else if (t->currentalpha < 1)
7614                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7615         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7616                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7617         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7618                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7619         if (t->backgroundnumskinframes)
7620                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7621         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7622         {
7623                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7624                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7625         }
7626         else
7627                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7628         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7629                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7630
7631         // there is no tcmod
7632         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7633         {
7634                 t->currenttexmatrix = r_waterscrollmatrix;
7635                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7636         }
7637         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7638         {
7639                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7640                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7641         }
7642
7643         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7644                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7645         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7646                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7647
7648         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7649         if (t->currentskinframe->qpixels)
7650                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7651         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7652         if (!t->basetexture)
7653                 t->basetexture = r_texture_notexture;
7654         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7655         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7656         t->nmaptexture = t->currentskinframe->nmap;
7657         if (!t->nmaptexture)
7658                 t->nmaptexture = r_texture_blanknormalmap;
7659         t->glosstexture = r_texture_black;
7660         t->glowtexture = t->currentskinframe->glow;
7661         t->fogtexture = t->currentskinframe->fog;
7662         t->reflectmasktexture = t->currentskinframe->reflect;
7663         if (t->backgroundnumskinframes)
7664         {
7665                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7666                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7667                 t->backgroundglosstexture = r_texture_black;
7668                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7669                 if (!t->backgroundnmaptexture)
7670                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7671         }
7672         else
7673         {
7674                 t->backgroundbasetexture = r_texture_white;
7675                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7676                 t->backgroundglosstexture = r_texture_black;
7677                 t->backgroundglowtexture = NULL;
7678         }
7679         t->specularpower = r_shadow_glossexponent.value;
7680         // TODO: store reference values for these in the texture?
7681         t->specularscale = 0;
7682         if (r_shadow_gloss.integer > 0)
7683         {
7684                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7685                 {
7686                         if (r_shadow_glossintensity.value > 0)
7687                         {
7688                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7689                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7690                                 t->specularscale = r_shadow_glossintensity.value;
7691                         }
7692                 }
7693                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7694                 {
7695                         t->glosstexture = r_texture_white;
7696                         t->backgroundglosstexture = r_texture_white;
7697                         t->specularscale = r_shadow_gloss2intensity.value;
7698                         t->specularpower = r_shadow_gloss2exponent.value;
7699                 }
7700         }
7701         t->specularscale *= t->specularscalemod;
7702         t->specularpower *= t->specularpowermod;
7703
7704         // lightmaps mode looks bad with dlights using actual texturing, so turn
7705         // off the colormap and glossmap, but leave the normalmap on as it still
7706         // accurately represents the shading involved
7707         if (gl_lightmaps.integer)
7708         {
7709                 t->basetexture = r_texture_grey128;
7710                 t->pantstexture = r_texture_black;
7711                 t->shirttexture = r_texture_black;
7712                 t->nmaptexture = r_texture_blanknormalmap;
7713                 t->glosstexture = r_texture_black;
7714                 t->glowtexture = NULL;
7715                 t->fogtexture = NULL;
7716                 t->reflectmasktexture = NULL;
7717                 t->backgroundbasetexture = NULL;
7718                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7719                 t->backgroundglosstexture = r_texture_black;
7720                 t->backgroundglowtexture = NULL;
7721                 t->specularscale = 0;
7722                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7723         }
7724
7725         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7726         VectorClear(t->dlightcolor);
7727         t->currentnumlayers = 0;
7728         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7729         {
7730                 int blendfunc1, blendfunc2;
7731                 qboolean depthmask;
7732                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7733                 {
7734                         blendfunc1 = GL_SRC_ALPHA;
7735                         blendfunc2 = GL_ONE;
7736                 }
7737                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7738                 {
7739                         blendfunc1 = GL_SRC_ALPHA;
7740                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7741                 }
7742                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7743                 {
7744                         blendfunc1 = t->customblendfunc[0];
7745                         blendfunc2 = t->customblendfunc[1];
7746                 }
7747                 else
7748                 {
7749                         blendfunc1 = GL_ONE;
7750                         blendfunc2 = GL_ZERO;
7751                 }
7752                 // don't colormod evilblend textures
7753                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7754                         VectorSet(t->lightmapcolor, 1, 1, 1);
7755                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7756                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7757                 {
7758                         // fullbright is not affected by r_refdef.lightmapintensity
7759                         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]);
7760                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7761                                 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]);
7762                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7763                                 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]);
7764                 }
7765                 else
7766                 {
7767                         vec3_t ambientcolor;
7768                         float colorscale;
7769                         // set the color tint used for lights affecting this surface
7770                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7771                         colorscale = 2;
7772                         // q3bsp has no lightmap updates, so the lightstylevalue that
7773                         // would normally be baked into the lightmap must be
7774                         // applied to the color
7775                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7776                         if (model->type == mod_brushq3)
7777                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7778                         colorscale *= r_refdef.lightmapintensity;
7779                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7780                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7781                         // basic lit geometry
7782                         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]);
7783                         // add pants/shirt if needed
7784                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7785                                 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]);
7786                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7787                                 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]);
7788                         // now add ambient passes if needed
7789                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7790                         {
7791                                 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]);
7792                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7793                                         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]);
7794                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7795                                         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]);
7796                         }
7797                 }
7798                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7799                         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]);
7800                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7801                 {
7802                         // if this is opaque use alpha blend which will darken the earlier
7803                         // passes cheaply.
7804                         //
7805                         // if this is an alpha blended material, all the earlier passes
7806                         // were darkened by fog already, so we only need to add the fog
7807                         // color ontop through the fog mask texture
7808                         //
7809                         // if this is an additive blended material, all the earlier passes
7810                         // were darkened by fog already, and we should not add fog color
7811                         // (because the background was not darkened, there is no fog color
7812                         // that was lost behind it).
7813                         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]);
7814                 }
7815         }
7816
7817         return t->currentframe;
7818 }
7819
7820 rsurfacestate_t rsurface;
7821
7822 void RSurf_ActiveWorldEntity(void)
7823 {
7824         dp_model_t *model = r_refdef.scene.worldmodel;
7825         //if (rsurface.entity == r_refdef.scene.worldentity)
7826         //      return;
7827         rsurface.entity = r_refdef.scene.worldentity;
7828         rsurface.skeleton = NULL;
7829         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7830         rsurface.ent_skinnum = 0;
7831         rsurface.ent_qwskin = -1;
7832         rsurface.ent_shadertime = 0;
7833         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7834         rsurface.matrix = identitymatrix;
7835         rsurface.inversematrix = identitymatrix;
7836         rsurface.matrixscale = 1;
7837         rsurface.inversematrixscale = 1;
7838         R_EntityMatrix(&identitymatrix);
7839         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7840         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7841         rsurface.fograngerecip = r_refdef.fograngerecip;
7842         rsurface.fogheightfade = r_refdef.fogheightfade;
7843         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7844         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7845         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7846         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7847         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7848         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7849         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7850         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7851         rsurface.colormod[3] = 1;
7852         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);
7853         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7854         rsurface.frameblend[0].lerp = 1;
7855         rsurface.ent_alttextures = false;
7856         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7857         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7858         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7859         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7860         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7861         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7862         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7863         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7864         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7865         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7866         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7867         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7868         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7869         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7870         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7871         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7872         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7873         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7874         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7875         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7876         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7877         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7878         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7879         rsurface.modelelement3i = model->surfmesh.data_element3i;
7880         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7881         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7882         rsurface.modelelement3s = model->surfmesh.data_element3s;
7883         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7884         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7885         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7886         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7887         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7888         rsurface.modelsurfaces = model->data_surfaces;
7889         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7890         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7891         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7892         rsurface.modelgeneratedvertex = false;
7893         rsurface.batchgeneratedvertex = false;
7894         rsurface.batchfirstvertex = 0;
7895         rsurface.batchnumvertices = 0;
7896         rsurface.batchfirsttriangle = 0;
7897         rsurface.batchnumtriangles = 0;
7898         rsurface.batchvertex3f  = NULL;
7899         rsurface.batchvertex3f_vertexbuffer = NULL;
7900         rsurface.batchvertex3f_bufferoffset = 0;
7901         rsurface.batchsvector3f = NULL;
7902         rsurface.batchsvector3f_vertexbuffer = NULL;
7903         rsurface.batchsvector3f_bufferoffset = 0;
7904         rsurface.batchtvector3f = NULL;
7905         rsurface.batchtvector3f_vertexbuffer = NULL;
7906         rsurface.batchtvector3f_bufferoffset = 0;
7907         rsurface.batchnormal3f  = NULL;
7908         rsurface.batchnormal3f_vertexbuffer = NULL;
7909         rsurface.batchnormal3f_bufferoffset = 0;
7910         rsurface.batchlightmapcolor4f = NULL;
7911         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7912         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7913         rsurface.batchtexcoordtexture2f = NULL;
7914         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7915         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7916         rsurface.batchtexcoordlightmap2f = NULL;
7917         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7918         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7919         rsurface.batchvertexmesh = NULL;
7920         rsurface.batchvertexmeshbuffer = NULL;
7921         rsurface.batchvertex3fbuffer = NULL;
7922         rsurface.batchelement3i = NULL;
7923         rsurface.batchelement3i_indexbuffer = NULL;
7924         rsurface.batchelement3i_bufferoffset = 0;
7925         rsurface.batchelement3s = NULL;
7926         rsurface.batchelement3s_indexbuffer = NULL;
7927         rsurface.batchelement3s_bufferoffset = 0;
7928         rsurface.passcolor4f = NULL;
7929         rsurface.passcolor4f_vertexbuffer = NULL;
7930         rsurface.passcolor4f_bufferoffset = 0;
7931 }
7932
7933 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7934 {
7935         dp_model_t *model = ent->model;
7936         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7937         //      return;
7938         rsurface.entity = (entity_render_t *)ent;
7939         rsurface.skeleton = ent->skeleton;
7940         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7941         rsurface.ent_skinnum = ent->skinnum;
7942         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;
7943         rsurface.ent_shadertime = ent->shadertime;
7944         rsurface.ent_flags = ent->flags;
7945         rsurface.matrix = ent->matrix;
7946         rsurface.inversematrix = ent->inversematrix;
7947         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7948         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7949         R_EntityMatrix(&rsurface.matrix);
7950         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7951         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7952         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7953         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7954         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7955         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7956         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7957         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7958         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7959         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7960         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7961         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7962         rsurface.colormod[3] = ent->alpha;
7963         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7964         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7965         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7966         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7967         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7968         if (ent->model->brush.submodel && !prepass)
7969         {
7970                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7971                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7972         }
7973         if (model->surfmesh.isanimated && model->AnimateVertices)
7974         {
7975                 if (ent->animcache_vertex3f)
7976                 {
7977                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7978                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7979                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7980                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7981                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7982                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7983                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7984                 }
7985                 else if (wanttangents)
7986                 {
7987                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7988                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7989                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7990                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7991                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7992                         rsurface.modelvertexmesh = NULL;
7993                         rsurface.modelvertexmeshbuffer = NULL;
7994                         rsurface.modelvertex3fbuffer = NULL;
7995                 }
7996                 else if (wantnormals)
7997                 {
7998                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7999                         rsurface.modelsvector3f = NULL;
8000                         rsurface.modeltvector3f = NULL;
8001                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8002                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8003                         rsurface.modelvertexmesh = NULL;
8004                         rsurface.modelvertexmeshbuffer = NULL;
8005                         rsurface.modelvertex3fbuffer = NULL;
8006                 }
8007                 else
8008                 {
8009                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8010                         rsurface.modelsvector3f = NULL;
8011                         rsurface.modeltvector3f = NULL;
8012                         rsurface.modelnormal3f = NULL;
8013                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8014                         rsurface.modelvertexmesh = NULL;
8015                         rsurface.modelvertexmeshbuffer = NULL;
8016                         rsurface.modelvertex3fbuffer = NULL;
8017                 }
8018                 rsurface.modelvertex3f_vertexbuffer = 0;
8019                 rsurface.modelvertex3f_bufferoffset = 0;
8020                 rsurface.modelsvector3f_vertexbuffer = 0;
8021                 rsurface.modelsvector3f_bufferoffset = 0;
8022                 rsurface.modeltvector3f_vertexbuffer = 0;
8023                 rsurface.modeltvector3f_bufferoffset = 0;
8024                 rsurface.modelnormal3f_vertexbuffer = 0;
8025                 rsurface.modelnormal3f_bufferoffset = 0;
8026                 rsurface.modelgeneratedvertex = true;
8027         }
8028         else
8029         {
8030                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8031                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8032                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8033                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8034                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8035                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8036                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8037                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8038                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8039                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8040                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8041                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8042                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8043                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8044                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8045                 rsurface.modelgeneratedvertex = false;
8046         }
8047         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8048         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8050         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8051         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8053         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8054         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8056         rsurface.modelelement3i = model->surfmesh.data_element3i;
8057         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8058         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8059         rsurface.modelelement3s = model->surfmesh.data_element3s;
8060         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8061         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8062         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8063         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8064         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8065         rsurface.modelsurfaces = model->data_surfaces;
8066         rsurface.batchgeneratedvertex = false;
8067         rsurface.batchfirstvertex = 0;
8068         rsurface.batchnumvertices = 0;
8069         rsurface.batchfirsttriangle = 0;
8070         rsurface.batchnumtriangles = 0;
8071         rsurface.batchvertex3f  = NULL;
8072         rsurface.batchvertex3f_vertexbuffer = NULL;
8073         rsurface.batchvertex3f_bufferoffset = 0;
8074         rsurface.batchsvector3f = NULL;
8075         rsurface.batchsvector3f_vertexbuffer = NULL;
8076         rsurface.batchsvector3f_bufferoffset = 0;
8077         rsurface.batchtvector3f = NULL;
8078         rsurface.batchtvector3f_vertexbuffer = NULL;
8079         rsurface.batchtvector3f_bufferoffset = 0;
8080         rsurface.batchnormal3f  = NULL;
8081         rsurface.batchnormal3f_vertexbuffer = NULL;
8082         rsurface.batchnormal3f_bufferoffset = 0;
8083         rsurface.batchlightmapcolor4f = NULL;
8084         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8085         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8086         rsurface.batchtexcoordtexture2f = NULL;
8087         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8088         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8089         rsurface.batchtexcoordlightmap2f = NULL;
8090         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8091         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8092         rsurface.batchvertexmesh = NULL;
8093         rsurface.batchvertexmeshbuffer = NULL;
8094         rsurface.batchvertex3fbuffer = NULL;
8095         rsurface.batchelement3i = NULL;
8096         rsurface.batchelement3i_indexbuffer = NULL;
8097         rsurface.batchelement3i_bufferoffset = 0;
8098         rsurface.batchelement3s = NULL;
8099         rsurface.batchelement3s_indexbuffer = NULL;
8100         rsurface.batchelement3s_bufferoffset = 0;
8101         rsurface.passcolor4f = NULL;
8102         rsurface.passcolor4f_vertexbuffer = NULL;
8103         rsurface.passcolor4f_bufferoffset = 0;
8104 }
8105
8106 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)
8107 {
8108         rsurface.entity = r_refdef.scene.worldentity;
8109         rsurface.skeleton = NULL;
8110         rsurface.ent_skinnum = 0;
8111         rsurface.ent_qwskin = -1;
8112         rsurface.ent_shadertime = shadertime;
8113         rsurface.ent_flags = entflags;
8114         rsurface.modelnumvertices = numvertices;
8115         rsurface.modelnumtriangles = numtriangles;
8116         rsurface.matrix = *matrix;
8117         rsurface.inversematrix = *inversematrix;
8118         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8119         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8120         R_EntityMatrix(&rsurface.matrix);
8121         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8122         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8123         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8124         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8125         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8126         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8127         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8128         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8129         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8130         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8131         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8132         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8133         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);
8134         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8135         rsurface.frameblend[0].lerp = 1;
8136         rsurface.ent_alttextures = false;
8137         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8138         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8139         if (wanttangents)
8140         {
8141                 rsurface.modelvertex3f = (float *)vertex3f;
8142                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8143                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8144                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8145         }
8146         else if (wantnormals)
8147         {
8148                 rsurface.modelvertex3f = (float *)vertex3f;
8149                 rsurface.modelsvector3f = NULL;
8150                 rsurface.modeltvector3f = NULL;
8151                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8152         }
8153         else
8154         {
8155                 rsurface.modelvertex3f = (float *)vertex3f;
8156                 rsurface.modelsvector3f = NULL;
8157                 rsurface.modeltvector3f = NULL;
8158                 rsurface.modelnormal3f = NULL;
8159         }
8160         rsurface.modelvertexmesh = NULL;
8161         rsurface.modelvertexmeshbuffer = NULL;
8162         rsurface.modelvertex3fbuffer = NULL;
8163         rsurface.modelvertex3f_vertexbuffer = 0;
8164         rsurface.modelvertex3f_bufferoffset = 0;
8165         rsurface.modelsvector3f_vertexbuffer = 0;
8166         rsurface.modelsvector3f_bufferoffset = 0;
8167         rsurface.modeltvector3f_vertexbuffer = 0;
8168         rsurface.modeltvector3f_bufferoffset = 0;
8169         rsurface.modelnormal3f_vertexbuffer = 0;
8170         rsurface.modelnormal3f_bufferoffset = 0;
8171         rsurface.modelgeneratedvertex = true;
8172         rsurface.modellightmapcolor4f  = (float *)color4f;
8173         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8174         rsurface.modellightmapcolor4f_bufferoffset = 0;
8175         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8176         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8177         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8178         rsurface.modeltexcoordlightmap2f  = NULL;
8179         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8180         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8181         rsurface.modelelement3i = (int *)element3i;
8182         rsurface.modelelement3i_indexbuffer = NULL;
8183         rsurface.modelelement3i_bufferoffset = 0;
8184         rsurface.modelelement3s = (unsigned short *)element3s;
8185         rsurface.modelelement3s_indexbuffer = NULL;
8186         rsurface.modelelement3s_bufferoffset = 0;
8187         rsurface.modellightmapoffsets = NULL;
8188         rsurface.modelsurfaces = NULL;
8189         rsurface.batchgeneratedvertex = false;
8190         rsurface.batchfirstvertex = 0;
8191         rsurface.batchnumvertices = 0;
8192         rsurface.batchfirsttriangle = 0;
8193         rsurface.batchnumtriangles = 0;
8194         rsurface.batchvertex3f  = NULL;
8195         rsurface.batchvertex3f_vertexbuffer = NULL;
8196         rsurface.batchvertex3f_bufferoffset = 0;
8197         rsurface.batchsvector3f = NULL;
8198         rsurface.batchsvector3f_vertexbuffer = NULL;
8199         rsurface.batchsvector3f_bufferoffset = 0;
8200         rsurface.batchtvector3f = NULL;
8201         rsurface.batchtvector3f_vertexbuffer = NULL;
8202         rsurface.batchtvector3f_bufferoffset = 0;
8203         rsurface.batchnormal3f  = NULL;
8204         rsurface.batchnormal3f_vertexbuffer = NULL;
8205         rsurface.batchnormal3f_bufferoffset = 0;
8206         rsurface.batchlightmapcolor4f = NULL;
8207         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8208         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8209         rsurface.batchtexcoordtexture2f = NULL;
8210         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8211         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8212         rsurface.batchtexcoordlightmap2f = NULL;
8213         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8214         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8215         rsurface.batchvertexmesh = NULL;
8216         rsurface.batchvertexmeshbuffer = NULL;
8217         rsurface.batchvertex3fbuffer = NULL;
8218         rsurface.batchelement3i = NULL;
8219         rsurface.batchelement3i_indexbuffer = NULL;
8220         rsurface.batchelement3i_bufferoffset = 0;
8221         rsurface.batchelement3s = NULL;
8222         rsurface.batchelement3s_indexbuffer = NULL;
8223         rsurface.batchelement3s_bufferoffset = 0;
8224         rsurface.passcolor4f = NULL;
8225         rsurface.passcolor4f_vertexbuffer = NULL;
8226         rsurface.passcolor4f_bufferoffset = 0;
8227
8228         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8229         {
8230                 if ((wantnormals || wanttangents) && !normal3f)
8231                 {
8232                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8233                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8234                 }
8235                 if (wanttangents && !svector3f)
8236                 {
8237                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8238                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8239                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8240                 }
8241         }
8242 }
8243
8244 float RSurf_FogPoint(const float *v)
8245 {
8246         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8247         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8248         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8249         float FogHeightFade = r_refdef.fogheightfade;
8250         float fogfrac;
8251         unsigned int fogmasktableindex;
8252         if (r_refdef.fogplaneviewabove)
8253                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8254         else
8255                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8256         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8257         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8258 }
8259
8260 float RSurf_FogVertex(const float *v)
8261 {
8262         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8263         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8264         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8265         float FogHeightFade = rsurface.fogheightfade;
8266         float fogfrac;
8267         unsigned int fogmasktableindex;
8268         if (r_refdef.fogplaneviewabove)
8269                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8270         else
8271                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8272         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8273         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8274 }
8275
8276 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8277 {
8278         int i;
8279         for (i = 0;i < numelements;i++)
8280                 outelement3i[i] = inelement3i[i] + adjust;
8281 }
8282
8283 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8284 extern cvar_t gl_vbo;
8285 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8286 {
8287         int deformindex;
8288         int firsttriangle;
8289         int numtriangles;
8290         int firstvertex;
8291         int endvertex;
8292         int numvertices;
8293         int surfacefirsttriangle;
8294         int surfacenumtriangles;
8295         int surfacefirstvertex;
8296         int surfaceendvertex;
8297         int surfacenumvertices;
8298         int batchnumvertices;
8299         int batchnumtriangles;
8300         int needsupdate;
8301         int i, j;
8302         qboolean gaps;
8303         qboolean dynamicvertex;
8304         float amplitude;
8305         float animpos;
8306         float scale;
8307         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8308         float waveparms[4];
8309         q3shaderinfo_deform_t *deform;
8310         const msurface_t *surface, *firstsurface;
8311         r_vertexmesh_t *vertexmesh;
8312         if (!texturenumsurfaces)
8313                 return;
8314         // find vertex range of this surface batch
8315         gaps = false;
8316         firstsurface = texturesurfacelist[0];
8317         firsttriangle = firstsurface->num_firsttriangle;
8318         batchnumvertices = 0;
8319         batchnumtriangles = 0;
8320         firstvertex = endvertex = firstsurface->num_firstvertex;
8321         for (i = 0;i < texturenumsurfaces;i++)
8322         {
8323                 surface = texturesurfacelist[i];
8324                 if (surface != firstsurface + i)
8325                         gaps = true;
8326                 surfacefirstvertex = surface->num_firstvertex;
8327                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8328                 surfacenumvertices = surface->num_vertices;
8329                 surfacenumtriangles = surface->num_triangles;
8330                 if (firstvertex > surfacefirstvertex)
8331                         firstvertex = surfacefirstvertex;
8332                 if (endvertex < surfaceendvertex)
8333                         endvertex = surfaceendvertex;
8334                 batchnumvertices += surfacenumvertices;
8335                 batchnumtriangles += surfacenumtriangles;
8336         }
8337
8338         // we now know the vertex range used, and if there are any gaps in it
8339         rsurface.batchfirstvertex = firstvertex;
8340         rsurface.batchnumvertices = endvertex - firstvertex;
8341         rsurface.batchfirsttriangle = firsttriangle;
8342         rsurface.batchnumtriangles = batchnumtriangles;
8343
8344         // this variable holds flags for which properties have been updated that
8345         // may require regenerating vertexmesh array...
8346         needsupdate = 0;
8347
8348         // check if any dynamic vertex processing must occur
8349         dynamicvertex = false;
8350
8351         // if there is a chance of animated vertex colors, it's a dynamic batch
8352         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8353         {
8354                 dynamicvertex = true;
8355                 batchneed |= BATCHNEED_NOGAPS;
8356                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8357         }
8358
8359         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8360         {
8361                 switch (deform->deform)
8362                 {
8363                 default:
8364                 case Q3DEFORM_PROJECTIONSHADOW:
8365                 case Q3DEFORM_TEXT0:
8366                 case Q3DEFORM_TEXT1:
8367                 case Q3DEFORM_TEXT2:
8368                 case Q3DEFORM_TEXT3:
8369                 case Q3DEFORM_TEXT4:
8370                 case Q3DEFORM_TEXT5:
8371                 case Q3DEFORM_TEXT6:
8372                 case Q3DEFORM_TEXT7:
8373                 case Q3DEFORM_NONE:
8374                         break;
8375                 case Q3DEFORM_AUTOSPRITE:
8376                         dynamicvertex = true;
8377                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8378                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8379                         break;
8380                 case Q3DEFORM_AUTOSPRITE2:
8381                         dynamicvertex = true;
8382                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8383                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8384                         break;
8385                 case Q3DEFORM_NORMAL:
8386                         dynamicvertex = true;
8387                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8388                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8389                         break;
8390                 case Q3DEFORM_WAVE:
8391                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8392                                 break; // if wavefunc is a nop, ignore this transform
8393                         dynamicvertex = true;
8394                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8395                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8396                         break;
8397                 case Q3DEFORM_BULGE:
8398                         dynamicvertex = true;
8399                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8400                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8401                         break;
8402                 case Q3DEFORM_MOVE:
8403                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8404                                 break; // if wavefunc is a nop, ignore this transform
8405                         dynamicvertex = true;
8406                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8407                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8408                         break;
8409                 }
8410         }
8411         switch(rsurface.texture->tcgen.tcgen)
8412         {
8413         default:
8414         case Q3TCGEN_TEXTURE:
8415                 break;
8416         case Q3TCGEN_LIGHTMAP:
8417                 dynamicvertex = true;
8418                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8419                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8420                 break;
8421         case Q3TCGEN_VECTOR:
8422                 dynamicvertex = true;
8423                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8424                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8425                 break;
8426         case Q3TCGEN_ENVIRONMENT:
8427                 dynamicvertex = true;
8428                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8429                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8430                 break;
8431         }
8432         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8433         {
8434                 dynamicvertex = true;
8435                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8436                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8437         }
8438
8439         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8440         {
8441                 dynamicvertex = true;
8442                 batchneed |= BATCHNEED_NOGAPS;
8443                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8444         }
8445
8446         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8447         {
8448                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8449                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8450                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8451                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8452                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8453                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8454                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8455         }
8456
8457         // when the model data has no vertex buffer (dynamic mesh), we need to
8458         // eliminate gaps
8459         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8460                 batchneed |= BATCHNEED_NOGAPS;
8461
8462         // if needsupdate, we have to do a dynamic vertex batch for sure
8463         if (needsupdate & batchneed)
8464                 dynamicvertex = true;
8465
8466         // see if we need to build vertexmesh from arrays
8467         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8468                 dynamicvertex = true;
8469
8470         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8471         // also some drivers strongly dislike firstvertex
8472         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8473                 dynamicvertex = true;
8474
8475         rsurface.batchvertex3f = rsurface.modelvertex3f;
8476         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8477         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8478         rsurface.batchsvector3f = rsurface.modelsvector3f;
8479         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8480         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8481         rsurface.batchtvector3f = rsurface.modeltvector3f;
8482         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8483         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8484         rsurface.batchnormal3f = rsurface.modelnormal3f;
8485         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8486         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8487         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8488         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8489         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8490         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8491         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8492         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8493         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8494         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8495         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8496         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8497         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8498         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8499         rsurface.batchelement3i = rsurface.modelelement3i;
8500         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8501         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8502         rsurface.batchelement3s = rsurface.modelelement3s;
8503         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8504         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8505
8506         // if any dynamic vertex processing has to occur in software, we copy the
8507         // entire surface list together before processing to rebase the vertices
8508         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8509         //
8510         // if any gaps exist and we do not have a static vertex buffer, we have to
8511         // copy the surface list together to avoid wasting upload bandwidth on the
8512         // vertices in the gaps.
8513         //
8514         // if gaps exist and we have a static vertex buffer, we still have to
8515         // combine the index buffer ranges into one dynamic index buffer.
8516         //
8517         // in all cases we end up with data that can be drawn in one call.
8518
8519         if (!dynamicvertex)
8520         {
8521                 // static vertex data, just set pointers...
8522                 rsurface.batchgeneratedvertex = false;
8523                 // if there are gaps, we want to build a combined index buffer,
8524                 // otherwise use the original static buffer with an appropriate offset
8525                 if (gaps)
8526                 {
8527                         // build a new triangle elements array for this batch
8528                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8529                         rsurface.batchfirsttriangle = 0;
8530                         numtriangles = 0;
8531                         for (i = 0;i < texturenumsurfaces;i++)
8532                         {
8533                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8534                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8535                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8536                                 numtriangles += surfacenumtriangles;
8537                         }
8538                         rsurface.batchelement3i_indexbuffer = NULL;
8539                         rsurface.batchelement3i_bufferoffset = 0;
8540                         rsurface.batchelement3s = NULL;
8541                         rsurface.batchelement3s_indexbuffer = NULL;
8542                         rsurface.batchelement3s_bufferoffset = 0;
8543                         if (endvertex <= 65536)
8544                         {
8545                                 // make a 16bit (unsigned short) index array if possible
8546                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8547                                 for (i = 0;i < numtriangles*3;i++)
8548                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8549                         }
8550                 }
8551                 return;
8552         }
8553
8554         // something needs software processing, do it for real...
8555         // we only directly handle separate array data in this case and then
8556         // generate interleaved data if needed...
8557         rsurface.batchgeneratedvertex = true;
8558
8559         // now copy the vertex data into a combined array and make an index array
8560         // (this is what Quake3 does all the time)
8561         //if (gaps || rsurface.batchfirstvertex)
8562         {
8563                 rsurface.batchvertex3fbuffer = NULL;
8564                 rsurface.batchvertexmesh = NULL;
8565                 rsurface.batchvertexmeshbuffer = NULL;
8566                 rsurface.batchvertex3f = NULL;
8567                 rsurface.batchvertex3f_vertexbuffer = NULL;
8568                 rsurface.batchvertex3f_bufferoffset = 0;
8569                 rsurface.batchsvector3f = NULL;
8570                 rsurface.batchsvector3f_vertexbuffer = NULL;
8571                 rsurface.batchsvector3f_bufferoffset = 0;
8572                 rsurface.batchtvector3f = NULL;
8573                 rsurface.batchtvector3f_vertexbuffer = NULL;
8574                 rsurface.batchtvector3f_bufferoffset = 0;
8575                 rsurface.batchnormal3f = NULL;
8576                 rsurface.batchnormal3f_vertexbuffer = NULL;
8577                 rsurface.batchnormal3f_bufferoffset = 0;
8578                 rsurface.batchlightmapcolor4f = NULL;
8579                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8580                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8581                 rsurface.batchtexcoordtexture2f = NULL;
8582                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8583                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8584                 rsurface.batchtexcoordlightmap2f = NULL;
8585                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8586                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8587                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8588                 rsurface.batchelement3i_indexbuffer = NULL;
8589                 rsurface.batchelement3i_bufferoffset = 0;
8590                 rsurface.batchelement3s = NULL;
8591                 rsurface.batchelement3s_indexbuffer = NULL;
8592                 rsurface.batchelement3s_bufferoffset = 0;
8593                 // we'll only be setting up certain arrays as needed
8594                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8595                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8596                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8597                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8598                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8599                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8600                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8601                 {
8602                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8603                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8604                 }
8605                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8606                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8607                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8608                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8609                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8610                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8611                 numvertices = 0;
8612                 numtriangles = 0;
8613                 for (i = 0;i < texturenumsurfaces;i++)
8614                 {
8615                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8616                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8617                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8618                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8619                         // copy only the data requested
8620                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8621                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8622                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8623                         {
8624                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8625                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8626                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8627                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8628                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8629                                 {
8630                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8631                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8632                                 }
8633                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8634                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8635                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8636                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8637                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8638                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8639                         }
8640                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8641                         numvertices += surfacenumvertices;
8642                         numtriangles += surfacenumtriangles;
8643                 }
8644
8645                 // generate a 16bit index array as well if possible
8646                 // (in general, dynamic batches fit)
8647                 if (numvertices <= 65536)
8648                 {
8649                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8650                         for (i = 0;i < numtriangles*3;i++)
8651                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8652                 }
8653
8654                 // since we've copied everything, the batch now starts at 0
8655                 rsurface.batchfirstvertex = 0;
8656                 rsurface.batchnumvertices = batchnumvertices;
8657                 rsurface.batchfirsttriangle = 0;
8658                 rsurface.batchnumtriangles = batchnumtriangles;
8659         }
8660
8661         // q1bsp surfaces rendered in vertex color mode have to have colors
8662         // calculated based on lightstyles
8663         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8664         {
8665                 // generate color arrays for the surfaces in this list
8666                 int c[4];
8667                 int scale;
8668                 int size3;
8669                 const int *offsets;
8670                 const unsigned char *lm;
8671                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8672                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8673                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8674                 numvertices = 0;
8675                 for (i = 0;i < texturenumsurfaces;i++)
8676                 {
8677                         surface = texturesurfacelist[i];
8678                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8679                         surfacenumvertices = surface->num_vertices;
8680                         if (surface->lightmapinfo->samples)
8681                         {
8682                                 for (j = 0;j < surfacenumvertices;j++)
8683                                 {
8684                                         lm = surface->lightmapinfo->samples + offsets[j];
8685                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8686                                         VectorScale(lm, scale, c);
8687                                         if (surface->lightmapinfo->styles[1] != 255)
8688                                         {
8689                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8690                                                 lm += size3;
8691                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8692                                                 VectorMA(c, scale, lm, c);
8693                                                 if (surface->lightmapinfo->styles[2] != 255)
8694                                                 {
8695                                                         lm += size3;
8696                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8697                                                         VectorMA(c, scale, lm, c);
8698                                                         if (surface->lightmapinfo->styles[3] != 255)
8699                                                         {
8700                                                                 lm += size3;
8701                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8702                                                                 VectorMA(c, scale, lm, c);
8703                                                         }
8704                                                 }
8705                                         }
8706                                         c[0] >>= 7;
8707                                         c[1] >>= 7;
8708                                         c[2] >>= 7;
8709                                         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);
8710                                         numvertices++;
8711                                 }
8712                         }
8713                         else
8714                         {
8715                                 for (j = 0;j < surfacenumvertices;j++)
8716                                 {
8717                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8718                                         numvertices++;
8719                                 }
8720                         }
8721                 }
8722         }
8723
8724         // if vertices are deformed (sprite flares and things in maps, possibly
8725         // water waves, bulges and other deformations), modify the copied vertices
8726         // in place
8727         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8728         {
8729                 switch (deform->deform)
8730                 {
8731                 default:
8732                 case Q3DEFORM_PROJECTIONSHADOW:
8733                 case Q3DEFORM_TEXT0:
8734                 case Q3DEFORM_TEXT1:
8735                 case Q3DEFORM_TEXT2:
8736                 case Q3DEFORM_TEXT3:
8737                 case Q3DEFORM_TEXT4:
8738                 case Q3DEFORM_TEXT5:
8739                 case Q3DEFORM_TEXT6:
8740                 case Q3DEFORM_TEXT7:
8741                 case Q3DEFORM_NONE:
8742                         break;
8743                 case Q3DEFORM_AUTOSPRITE:
8744                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8745                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8746                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8747                         VectorNormalize(newforward);
8748                         VectorNormalize(newright);
8749                         VectorNormalize(newup);
8750 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8751 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8752 //                      rsurface.batchvertex3f_bufferoffset = 0;
8753 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8754 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8755 //                      rsurface.batchsvector3f_bufferoffset = 0;
8756 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8757 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8758 //                      rsurface.batchtvector3f_bufferoffset = 0;
8759 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8760 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8761 //                      rsurface.batchnormal3f_bufferoffset = 0;
8762                         // a single autosprite surface can contain multiple sprites...
8763                         for (j = 0;j < batchnumvertices - 3;j += 4)
8764                         {
8765                                 VectorClear(center);
8766                                 for (i = 0;i < 4;i++)
8767                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8768                                 VectorScale(center, 0.25f, center);
8769                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8770                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8771                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8772                                 for (i = 0;i < 4;i++)
8773                                 {
8774                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8775                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8776                                 }
8777                         }
8778                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8779                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8780                         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);
8781                         break;
8782                 case Q3DEFORM_AUTOSPRITE2:
8783                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8784                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8785                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8786                         VectorNormalize(newforward);
8787                         VectorNormalize(newright);
8788                         VectorNormalize(newup);
8789 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8790 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8791 //                      rsurface.batchvertex3f_bufferoffset = 0;
8792                         {
8793                                 const float *v1, *v2;
8794                                 vec3_t start, end;
8795                                 float f, l;
8796                                 struct
8797                                 {
8798                                         float length2;
8799                                         const float *v1;
8800                                         const float *v2;
8801                                 }
8802                                 shortest[2];
8803                                 memset(shortest, 0, sizeof(shortest));
8804                                 // a single autosprite surface can contain multiple sprites...
8805                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8806                                 {
8807                                         VectorClear(center);
8808                                         for (i = 0;i < 4;i++)
8809                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8810                                         VectorScale(center, 0.25f, center);
8811                                         // find the two shortest edges, then use them to define the
8812                                         // axis vectors for rotating around the central axis
8813                                         for (i = 0;i < 6;i++)
8814                                         {
8815                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8816                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8817                                                 l = VectorDistance2(v1, v2);
8818                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8819                                                 if (v1[2] != v2[2])
8820                                                         l += (1.0f / 1024.0f);
8821                                                 if (shortest[0].length2 > l || i == 0)
8822                                                 {
8823                                                         shortest[1] = shortest[0];
8824                                                         shortest[0].length2 = l;
8825                                                         shortest[0].v1 = v1;
8826                                                         shortest[0].v2 = v2;
8827                                                 }
8828                                                 else if (shortest[1].length2 > l || i == 1)
8829                                                 {
8830                                                         shortest[1].length2 = l;
8831                                                         shortest[1].v1 = v1;
8832                                                         shortest[1].v2 = v2;
8833                                                 }
8834                                         }
8835                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8836                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8837                                         // this calculates the right vector from the shortest edge
8838                                         // and the up vector from the edge midpoints
8839                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8840                                         VectorNormalize(right);
8841                                         VectorSubtract(end, start, up);
8842                                         VectorNormalize(up);
8843                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8844                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8845                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8846                                         VectorNegate(forward, forward);
8847                                         VectorReflect(forward, 0, up, forward);
8848                                         VectorNormalize(forward);
8849                                         CrossProduct(up, forward, newright);
8850                                         VectorNormalize(newright);
8851                                         // rotate the quad around the up axis vector, this is made
8852                                         // especially easy by the fact we know the quad is flat,
8853                                         // so we only have to subtract the center position and
8854                                         // measure distance along the right vector, and then
8855                                         // multiply that by the newright vector and add back the
8856                                         // center position
8857                                         // we also need to subtract the old position to undo the
8858                                         // displacement from the center, which we do with a
8859                                         // DotProduct, the subtraction/addition of center is also
8860                                         // optimized into DotProducts here
8861                                         l = DotProduct(right, center);
8862                                         for (i = 0;i < 4;i++)
8863                                         {
8864                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8865                                                 f = DotProduct(right, v1) - l;
8866                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8867                                         }
8868                                 }
8869                         }
8870                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8871                         {
8872 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8873 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8874 //                              rsurface.batchnormal3f_bufferoffset = 0;
8875                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8876                         }
8877                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8878                         {
8879 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8880 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8881 //                              rsurface.batchsvector3f_bufferoffset = 0;
8882 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8883 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8884 //                              rsurface.batchtvector3f_bufferoffset = 0;
8885                                 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);
8886                         }
8887                         break;
8888                 case Q3DEFORM_NORMAL:
8889                         // deform the normals to make reflections wavey
8890                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8891                         rsurface.batchnormal3f_vertexbuffer = NULL;
8892                         rsurface.batchnormal3f_bufferoffset = 0;
8893                         for (j = 0;j < batchnumvertices;j++)
8894                         {
8895                                 float vertex[3];
8896                                 float *normal = rsurface.batchnormal3f + 3*j;
8897                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8898                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8899                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8900                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8901                                 VectorNormalize(normal);
8902                         }
8903                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8904                         {
8905 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8906 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8907 //                              rsurface.batchsvector3f_bufferoffset = 0;
8908 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8909 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8910 //                              rsurface.batchtvector3f_bufferoffset = 0;
8911                                 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);
8912                         }
8913                         break;
8914                 case Q3DEFORM_WAVE:
8915                         // deform vertex array to make wavey water and flags and such
8916                         waveparms[0] = deform->waveparms[0];
8917                         waveparms[1] = deform->waveparms[1];
8918                         waveparms[2] = deform->waveparms[2];
8919                         waveparms[3] = deform->waveparms[3];
8920                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8921                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8922                         // this is how a divisor of vertex influence on deformation
8923                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8924                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8925 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8926 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8927 //                      rsurface.batchvertex3f_bufferoffset = 0;
8928 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8929 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8930 //                      rsurface.batchnormal3f_bufferoffset = 0;
8931                         for (j = 0;j < batchnumvertices;j++)
8932                         {
8933                                 // if the wavefunc depends on time, evaluate it per-vertex
8934                                 if (waveparms[3])
8935                                 {
8936                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8937                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8938                                 }
8939                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8940                         }
8941                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8942                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
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_BULGE:
8955                         // deform vertex array to make the surface have moving bulges
8956 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8957 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8958 //                      rsurface.batchvertex3f_bufferoffset = 0;
8959 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8960 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8961 //                      rsurface.batchnormal3f_bufferoffset = 0;
8962                         for (j = 0;j < batchnumvertices;j++)
8963                         {
8964                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8965                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8966                         }
8967                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8968                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
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_MOVE:
8981                         // deform vertex array
8982                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8983                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8984                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8985                         VectorScale(deform->parms, scale, waveparms);
8986 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8987 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8988 //                      rsurface.batchvertex3f_bufferoffset = 0;
8989                         for (j = 0;j < batchnumvertices;j++)
8990                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8991                         break;
8992                 }
8993         }
8994
8995         // generate texcoords based on the chosen texcoord source
8996         switch(rsurface.texture->tcgen.tcgen)
8997         {
8998         default:
8999         case Q3TCGEN_TEXTURE:
9000                 break;
9001         case Q3TCGEN_LIGHTMAP:
9002 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9003 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9004 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9005                 if (rsurface.batchtexcoordlightmap2f)
9006                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9007                 break;
9008         case Q3TCGEN_VECTOR:
9009 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9010 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9011 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9012                 for (j = 0;j < batchnumvertices;j++)
9013                 {
9014                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9015                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9016                 }
9017                 break;
9018         case Q3TCGEN_ENVIRONMENT:
9019                 // make environment reflections using a spheremap
9020                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9021                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9022                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9023                 for (j = 0;j < batchnumvertices;j++)
9024                 {
9025                         // identical to Q3A's method, but executed in worldspace so
9026                         // carried models can be shiny too
9027
9028                         float viewer[3], d, reflected[3], worldreflected[3];
9029
9030                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9031                         // VectorNormalize(viewer);
9032
9033                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9034
9035                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9036                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9037                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9038                         // note: this is proportinal to viewer, so we can normalize later
9039
9040                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9041                         VectorNormalize(worldreflected);
9042
9043                         // note: this sphere map only uses world x and z!
9044                         // so positive and negative y will LOOK THE SAME.
9045                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9046                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9047                 }
9048                 break;
9049         }
9050         // the only tcmod that needs software vertex processing is turbulent, so
9051         // check for it here and apply the changes if needed
9052         // and we only support that as the first one
9053         // (handling a mixture of turbulent and other tcmods would be problematic
9054         //  without punting it entirely to a software path)
9055         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9056         {
9057                 amplitude = rsurface.texture->tcmods[0].parms[1];
9058                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9059 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9060 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9061 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9062                 for (j = 0;j < batchnumvertices;j++)
9063                 {
9064                         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);
9065                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9066                 }
9067         }
9068
9069         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9070         {
9071                 // convert the modified arrays to vertex structs
9072 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9073 //              rsurface.batchvertexmeshbuffer = NULL;
9074                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9075                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9076                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9077                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9078                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9079                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9080                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9081                 {
9082                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9083                         {
9084                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9085                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9086                         }
9087                 }
9088                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9089                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9090                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9091                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9092                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9093                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9094                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9095                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9096                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9097         }
9098 }
9099
9100 void RSurf_DrawBatch(void)
9101 {
9102         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9103         // through the pipeline, killing it earlier in the pipeline would have
9104         // per-surface overhead rather than per-batch overhead, so it's best to
9105         // reject it here, before it hits glDraw.
9106         if (rsurface.batchnumtriangles == 0)
9107                 return;
9108 #if 0
9109         // batch debugging code
9110         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9111         {
9112                 int i;
9113                 int j;
9114                 int c;
9115                 const int *e;
9116                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9117                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9118                 {
9119                         c = e[i];
9120                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9121                         {
9122                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9123                                 {
9124                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9125                                                 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);
9126                                         break;
9127                                 }
9128                         }
9129                 }
9130         }
9131 #endif
9132         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);
9133 }
9134
9135 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9136 {
9137         // pick the closest matching water plane
9138         int planeindex, vertexindex, bestplaneindex = -1;
9139         float d, bestd;
9140         vec3_t vert;
9141         const float *v;
9142         r_waterstate_waterplane_t *p;
9143         qboolean prepared = false;
9144         bestd = 0;
9145         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9146         {
9147                 if(p->camera_entity != rsurface.texture->camera_entity)
9148                         continue;
9149                 d = 0;
9150                 if(!prepared)
9151                 {
9152                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9153                         prepared = true;
9154                         if(rsurface.batchnumvertices == 0)
9155                                 break;
9156                 }
9157                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9158                 {
9159                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9160                         d += fabs(PlaneDiff(vert, &p->plane));
9161                 }
9162                 if (bestd > d || bestplaneindex < 0)
9163                 {
9164                         bestd = d;
9165                         bestplaneindex = planeindex;
9166                 }
9167         }
9168         return bestplaneindex;
9169         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9170         // this situation though, as it might be better to render single larger
9171         // batches with useless stuff (backface culled for example) than to
9172         // render multiple smaller batches
9173 }
9174
9175 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9176 {
9177         int i;
9178         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9179         rsurface.passcolor4f_vertexbuffer = 0;
9180         rsurface.passcolor4f_bufferoffset = 0;
9181         for (i = 0;i < rsurface.batchnumvertices;i++)
9182                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9183 }
9184
9185 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9186 {
9187         int i;
9188         float f;
9189         const float *v;
9190         const float *c;
9191         float *c2;
9192         if (rsurface.passcolor4f)
9193         {
9194                 // generate color arrays
9195                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9196                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9197                 rsurface.passcolor4f_vertexbuffer = 0;
9198                 rsurface.passcolor4f_bufferoffset = 0;
9199                 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)
9200                 {
9201                         f = RSurf_FogVertex(v);
9202                         c2[0] = c[0] * f;
9203                         c2[1] = c[1] * f;
9204                         c2[2] = c[2] * f;
9205                         c2[3] = c[3];
9206                 }
9207         }
9208         else
9209         {
9210                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9211                 rsurface.passcolor4f_vertexbuffer = 0;
9212                 rsurface.passcolor4f_bufferoffset = 0;
9213                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9214                 {
9215                         f = RSurf_FogVertex(v);
9216                         c2[0] = f;
9217                         c2[1] = f;
9218                         c2[2] = f;
9219                         c2[3] = 1;
9220                 }
9221         }
9222 }
9223
9224 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9225 {
9226         int i;
9227         float f;
9228         const float *v;
9229         const float *c;
9230         float *c2;
9231         if (!rsurface.passcolor4f)
9232                 return;
9233         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9234         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9235         rsurface.passcolor4f_vertexbuffer = 0;
9236         rsurface.passcolor4f_bufferoffset = 0;
9237         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)
9238         {
9239                 f = RSurf_FogVertex(v);
9240                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9241                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9242                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9243                 c2[3] = c[3];
9244         }
9245 }
9246
9247 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9248 {
9249         int i;
9250         const float *c;
9251         float *c2;
9252         if (!rsurface.passcolor4f)
9253                 return;
9254         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9255         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9256         rsurface.passcolor4f_vertexbuffer = 0;
9257         rsurface.passcolor4f_bufferoffset = 0;
9258         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9259         {
9260                 c2[0] = c[0] * r;
9261                 c2[1] = c[1] * g;
9262                 c2[2] = c[2] * b;
9263                 c2[3] = c[3] * a;
9264         }
9265 }
9266
9267 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9268 {
9269         int i;
9270         const float *c;
9271         float *c2;
9272         if (!rsurface.passcolor4f)
9273                 return;
9274         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9275         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9276         rsurface.passcolor4f_vertexbuffer = 0;
9277         rsurface.passcolor4f_bufferoffset = 0;
9278         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9279         {
9280                 c2[0] = c[0] + r_refdef.scene.ambient;
9281                 c2[1] = c[1] + r_refdef.scene.ambient;
9282                 c2[2] = c[2] + r_refdef.scene.ambient;
9283                 c2[3] = c[3];
9284         }
9285 }
9286
9287 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9288 {
9289         // TODO: optimize
9290         rsurface.passcolor4f = NULL;
9291         rsurface.passcolor4f_vertexbuffer = 0;
9292         rsurface.passcolor4f_bufferoffset = 0;
9293         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9294         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9295         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9296         GL_Color(r, g, b, a);
9297         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9298         RSurf_DrawBatch();
9299 }
9300
9301 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9302 {
9303         // TODO: optimize applyfog && applycolor case
9304         // just apply fog if necessary, and tint the fog color array if necessary
9305         rsurface.passcolor4f = NULL;
9306         rsurface.passcolor4f_vertexbuffer = 0;
9307         rsurface.passcolor4f_bufferoffset = 0;
9308         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9309         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9310         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9311         GL_Color(r, g, b, a);
9312         RSurf_DrawBatch();
9313 }
9314
9315 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9316 {
9317         // TODO: optimize
9318         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9319         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9320         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9321         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9322         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9323         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9324         GL_Color(r, g, b, a);
9325         RSurf_DrawBatch();
9326 }
9327
9328 static void RSurf_DrawBatch_GL11_ClampColor(void)
9329 {
9330         int i;
9331         const float *c1;
9332         float *c2;
9333         if (!rsurface.passcolor4f)
9334                 return;
9335         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9336         {
9337                 c2[0] = bound(0.0f, c1[0], 1.0f);
9338                 c2[1] = bound(0.0f, c1[1], 1.0f);
9339                 c2[2] = bound(0.0f, c1[2], 1.0f);
9340                 c2[3] = bound(0.0f, c1[3], 1.0f);
9341         }
9342 }
9343
9344 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9345 {
9346         int i;
9347         float f;
9348         const float *v;
9349         const float *n;
9350         float *c;
9351         //vec3_t eyedir;
9352
9353         // fake shading
9354         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9355         rsurface.passcolor4f_vertexbuffer = 0;
9356         rsurface.passcolor4f_bufferoffset = 0;
9357         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)
9358         {
9359                 f = -DotProduct(r_refdef.view.forward, n);
9360                 f = max(0, f);
9361                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9362                 f *= r_refdef.lightmapintensity;
9363                 Vector4Set(c, f, f, f, 1);
9364         }
9365 }
9366
9367 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9368 {
9369         RSurf_DrawBatch_GL11_ApplyFakeLight();
9370         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9371         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9372         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9373         GL_Color(r, g, b, a);
9374         RSurf_DrawBatch();
9375 }
9376
9377 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9378 {
9379         int i;
9380         float f;
9381         float alpha;
9382         const float *v;
9383         const float *n;
9384         float *c;
9385         vec3_t ambientcolor;
9386         vec3_t diffusecolor;
9387         vec3_t lightdir;
9388         // TODO: optimize
9389         // model lighting
9390         VectorCopy(rsurface.modellight_lightdir, lightdir);
9391         f = 0.5f * r_refdef.lightmapintensity;
9392         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9393         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9394         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9395         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9396         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9397         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9398         alpha = *a;
9399         if (VectorLength2(diffusecolor) > 0)
9400         {
9401                 // q3-style directional shading
9402                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9403                 rsurface.passcolor4f_vertexbuffer = 0;
9404                 rsurface.passcolor4f_bufferoffset = 0;
9405                 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)
9406                 {
9407                         if ((f = DotProduct(n, lightdir)) > 0)
9408                                 VectorMA(ambientcolor, f, diffusecolor, c);
9409                         else
9410                                 VectorCopy(ambientcolor, c);
9411                         c[3] = alpha;
9412                 }
9413                 *r = 1;
9414                 *g = 1;
9415                 *b = 1;
9416                 *a = 1;
9417                 *applycolor = false;
9418         }
9419         else
9420         {
9421                 *r = ambientcolor[0];
9422                 *g = ambientcolor[1];
9423                 *b = ambientcolor[2];
9424                 rsurface.passcolor4f = NULL;
9425                 rsurface.passcolor4f_vertexbuffer = 0;
9426                 rsurface.passcolor4f_bufferoffset = 0;
9427         }
9428 }
9429
9430 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9431 {
9432         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9433         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9434         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9435         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9436         GL_Color(r, g, b, a);
9437         RSurf_DrawBatch();
9438 }
9439
9440 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9441 {
9442         int i;
9443         float f;
9444         const float *v;
9445         float *c;
9446
9447         // fake shading
9448         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9449         rsurface.passcolor4f_vertexbuffer = 0;
9450         rsurface.passcolor4f_bufferoffset = 0;
9451
9452         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9453         {
9454                 f = 1 - RSurf_FogVertex(v);
9455                 c[0] = r;
9456                 c[1] = g;
9457                 c[2] = b;
9458                 c[3] = f * a;
9459         }
9460 }
9461
9462 void RSurf_SetupDepthAndCulling(void)
9463 {
9464         // submodels are biased to avoid z-fighting with world surfaces that they
9465         // may be exactly overlapping (avoids z-fighting artifacts on certain
9466         // doors and things in Quake maps)
9467         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9468         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9469         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9470         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9471 }
9472
9473 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9474 {
9475         // transparent sky would be ridiculous
9476         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9477                 return;
9478         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9479         skyrenderlater = true;
9480         RSurf_SetupDepthAndCulling();
9481         GL_DepthMask(true);
9482         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9483         // skymasking on them, and Quake3 never did sky masking (unlike
9484         // software Quake and software Quake2), so disable the sky masking
9485         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9486         // and skymasking also looks very bad when noclipping outside the
9487         // level, so don't use it then either.
9488         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9489         {
9490                 R_Mesh_ResetTextureState();
9491                 if (skyrendermasked)
9492                 {
9493                         R_SetupShader_DepthOrShadow();
9494                         // depth-only (masking)
9495                         GL_ColorMask(0,0,0,0);
9496                         // just to make sure that braindead drivers don't draw
9497                         // anything despite that colormask...
9498                         GL_BlendFunc(GL_ZERO, GL_ONE);
9499                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9500                         if (rsurface.batchvertex3fbuffer)
9501                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9502                         else
9503                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9504                 }
9505                 else
9506                 {
9507                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9508                         // fog sky
9509                         GL_BlendFunc(GL_ONE, GL_ZERO);
9510                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9511                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9512                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9513                 }
9514                 RSurf_DrawBatch();
9515                 if (skyrendermasked)
9516                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9517         }
9518         R_Mesh_ResetTextureState();
9519         GL_Color(1, 1, 1, 1);
9520 }
9521
9522 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9523 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9524 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9525 {
9526         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9527                 return;
9528         if (prepass)
9529         {
9530                 // render screenspace normalmap to texture
9531                 GL_DepthMask(true);
9532                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9533                 RSurf_DrawBatch();
9534         }
9535
9536         // bind lightmap texture
9537
9538         // water/refraction/reflection/camera surfaces have to be handled specially
9539         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9540         {
9541                 int start, end, startplaneindex;
9542                 for (start = 0;start < texturenumsurfaces;start = end)
9543                 {
9544                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9545                         if(startplaneindex < 0)
9546                         {
9547                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9548                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9549                                 end = start + 1;
9550                                 continue;
9551                         }
9552                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9553                                 ;
9554                         // now that we have a batch using the same planeindex, render it
9555                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9556                         {
9557                                 // render water or distortion background
9558                                 GL_DepthMask(true);
9559                                 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));
9560                                 RSurf_DrawBatch();
9561                                 // blend surface on top
9562                                 GL_DepthMask(false);
9563                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9564                                 RSurf_DrawBatch();
9565                         }
9566                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9567                         {
9568                                 // render surface with reflection texture as input
9569                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9570                                 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));
9571                                 RSurf_DrawBatch();
9572                         }
9573                 }
9574                 return;
9575         }
9576
9577         // render surface batch normally
9578         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9579         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9580         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9581                 GL_AlphaTest(true);
9582         RSurf_DrawBatch();
9583         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9584                 GL_AlphaTest(false);
9585 }
9586
9587 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9588 {
9589         // OpenGL 1.3 path - anything not completely ancient
9590         qboolean applycolor;
9591         qboolean applyfog;
9592         int layerindex;
9593         const texturelayer_t *layer;
9594         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);
9595         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9596
9597         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9598         {
9599                 vec4_t layercolor;
9600                 int layertexrgbscale;
9601                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9602                 {
9603                         if (layerindex == 0)
9604                                 GL_AlphaTest(true);
9605                         else
9606                         {
9607                                 GL_AlphaTest(false);
9608                                 GL_DepthFunc(GL_EQUAL);
9609                         }
9610                 }
9611                 GL_DepthMask(layer->depthmask && writedepth);
9612                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9613                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9614                 {
9615                         layertexrgbscale = 4;
9616                         VectorScale(layer->color, 0.25f, layercolor);
9617                 }
9618                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9619                 {
9620                         layertexrgbscale = 2;
9621                         VectorScale(layer->color, 0.5f, layercolor);
9622                 }
9623                 else
9624                 {
9625                         layertexrgbscale = 1;
9626                         VectorScale(layer->color, 1.0f, layercolor);
9627                 }
9628                 layercolor[3] = layer->color[3];
9629                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9630                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9631                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9632                 switch (layer->type)
9633                 {
9634                 case TEXTURELAYERTYPE_LITTEXTURE:
9635                         // single-pass lightmapped texture with 2x rgbscale
9636                         R_Mesh_TexBind(0, r_texture_white);
9637                         R_Mesh_TexMatrix(0, NULL);
9638                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9639                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9640                         R_Mesh_TexBind(1, layer->texture);
9641                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9642                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9643                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9644                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9645                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9646                         else if (FAKELIGHT_ENABLED)
9647                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9648                         else if (rsurface.uselightmaptexture)
9649                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9650                         else
9651                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9652                         break;
9653                 case TEXTURELAYERTYPE_TEXTURE:
9654                         // singletexture unlit texture with transparency support
9655                         R_Mesh_TexBind(0, layer->texture);
9656                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9657                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9658                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9659                         R_Mesh_TexBind(1, 0);
9660                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9661                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9662                         break;
9663                 case TEXTURELAYERTYPE_FOG:
9664                         // singletexture fogging
9665                         if (layer->texture)
9666                         {
9667                                 R_Mesh_TexBind(0, layer->texture);
9668                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9669                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9670                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9671                         }
9672                         else
9673                         {
9674                                 R_Mesh_TexBind(0, 0);
9675                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9676                         }
9677                         R_Mesh_TexBind(1, 0);
9678                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9679                         // generate a color array for the fog pass
9680                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9681                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9682                         RSurf_DrawBatch();
9683                         break;
9684                 default:
9685                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9686                 }
9687         }
9688         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9689         {
9690                 GL_DepthFunc(GL_LEQUAL);
9691                 GL_AlphaTest(false);
9692         }
9693 }
9694
9695 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9696 {
9697         // OpenGL 1.1 - crusty old voodoo path
9698         qboolean applyfog;
9699         int layerindex;
9700         const texturelayer_t *layer;
9701         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);
9702         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9703
9704         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9705         {
9706                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9707                 {
9708                         if (layerindex == 0)
9709                                 GL_AlphaTest(true);
9710                         else
9711                         {
9712                                 GL_AlphaTest(false);
9713                                 GL_DepthFunc(GL_EQUAL);
9714                         }
9715                 }
9716                 GL_DepthMask(layer->depthmask && writedepth);
9717                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9718                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9719                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9720                 switch (layer->type)
9721                 {
9722                 case TEXTURELAYERTYPE_LITTEXTURE:
9723                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9724                         {
9725                                 // two-pass lit texture with 2x rgbscale
9726                                 // first the lightmap pass
9727                                 R_Mesh_TexBind(0, r_texture_white);
9728                                 R_Mesh_TexMatrix(0, NULL);
9729                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9730                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9731                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9732                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9733                                 else if (FAKELIGHT_ENABLED)
9734                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9735                                 else if (rsurface.uselightmaptexture)
9736                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9737                                 else
9738                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9739                                 // then apply the texture to it
9740                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9741                                 R_Mesh_TexBind(0, layer->texture);
9742                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9743                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9744                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9745                                 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);
9746                         }
9747                         else
9748                         {
9749                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9750                                 R_Mesh_TexBind(0, layer->texture);
9751                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9752                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9753                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9754                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9755                                         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);
9756                                 else
9757                                         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);
9758                         }
9759                         break;
9760                 case TEXTURELAYERTYPE_TEXTURE:
9761                         // singletexture unlit texture with transparency support
9762                         R_Mesh_TexBind(0, layer->texture);
9763                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9764                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9765                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9766                         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);
9767                         break;
9768                 case TEXTURELAYERTYPE_FOG:
9769                         // singletexture fogging
9770                         if (layer->texture)
9771                         {
9772                                 R_Mesh_TexBind(0, layer->texture);
9773                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9774                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9775                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9776                         }
9777                         else
9778                         {
9779                                 R_Mesh_TexBind(0, 0);
9780                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9781                         }
9782                         // generate a color array for the fog pass
9783                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9784                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9785                         RSurf_DrawBatch();
9786                         break;
9787                 default:
9788                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9789                 }
9790         }
9791         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9792         {
9793                 GL_DepthFunc(GL_LEQUAL);
9794                 GL_AlphaTest(false);
9795         }
9796 }
9797
9798 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9799 {
9800         int vi;
9801         int j;
9802         r_vertexgeneric_t *batchvertex;
9803         float c[4];
9804
9805 //      R_Mesh_ResetTextureState();
9806         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9807
9808         if(rsurface.texture && rsurface.texture->currentskinframe)
9809         {
9810                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9811                 c[3] *= rsurface.texture->currentalpha;
9812         }
9813         else
9814         {
9815                 c[0] = 1;
9816                 c[1] = 0;
9817                 c[2] = 1;
9818                 c[3] = 1;
9819         }
9820
9821         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9822         {
9823                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9824                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9825                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9826         }
9827
9828         // brighten it up (as texture value 127 means "unlit")
9829         c[0] *= 2 * r_refdef.view.colorscale;
9830         c[1] *= 2 * r_refdef.view.colorscale;
9831         c[2] *= 2 * r_refdef.view.colorscale;
9832
9833         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9834                 c[3] *= r_wateralpha.value;
9835
9836         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9837         {
9838                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9839                 GL_DepthMask(false);
9840         }
9841         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9842         {
9843                 GL_BlendFunc(GL_ONE, GL_ONE);
9844                 GL_DepthMask(false);
9845         }
9846         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9847         {
9848                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9849                 GL_DepthMask(false);
9850         }
9851         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9852         {
9853                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9854                 GL_DepthMask(false);
9855         }
9856         else
9857         {
9858                 GL_BlendFunc(GL_ONE, GL_ZERO);
9859                 GL_DepthMask(writedepth);
9860         }
9861
9862         if (r_showsurfaces.integer == 3)
9863         {
9864                 rsurface.passcolor4f = NULL;
9865
9866                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9867                 {
9868                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9869
9870                         rsurface.passcolor4f = NULL;
9871                         rsurface.passcolor4f_vertexbuffer = 0;
9872                         rsurface.passcolor4f_bufferoffset = 0;
9873                 }
9874                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9875                 {
9876                         qboolean applycolor = true;
9877                         float one = 1.0;
9878
9879                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9880
9881                         r_refdef.lightmapintensity = 1;
9882                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9883                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9884                 }
9885                 else if (FAKELIGHT_ENABLED)
9886                 {
9887                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9888
9889                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9890                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9891                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9892                 }
9893                 else
9894                 {
9895                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9896
9897                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9898                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9899                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9900                 }
9901
9902                 if(!rsurface.passcolor4f)
9903                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9904
9905                 RSurf_DrawBatch_GL11_ApplyAmbient();
9906                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9907                 if(r_refdef.fogenabled)
9908                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9909                 RSurf_DrawBatch_GL11_ClampColor();
9910
9911                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9912                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9913                 RSurf_DrawBatch();
9914         }
9915         else if (!r_refdef.view.showdebug)
9916         {
9917                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9918                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9919                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9920                 {
9921                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9922                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9923                 }
9924                 R_Mesh_PrepareVertices_Generic_Unlock();
9925                 RSurf_DrawBatch();
9926         }
9927         else if (r_showsurfaces.integer == 4)
9928         {
9929                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9930                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9931                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9932                 {
9933                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9934                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9935                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9936                 }
9937                 R_Mesh_PrepareVertices_Generic_Unlock();
9938                 RSurf_DrawBatch();
9939         }
9940         else if (r_showsurfaces.integer == 2)
9941         {
9942                 const int *e;
9943                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9944                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9945                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9946                 {
9947                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9948                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9949                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9950                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9951                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9952                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9953                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9954                 }
9955                 R_Mesh_PrepareVertices_Generic_Unlock();
9956                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9957         }
9958         else
9959         {
9960                 int texturesurfaceindex;
9961                 int k;
9962                 const msurface_t *surface;
9963                 float surfacecolor4f[4];
9964                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9965                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9966                 vi = 0;
9967                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9968                 {
9969                         surface = texturesurfacelist[texturesurfaceindex];
9970                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9971                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9972                         for (j = 0;j < surface->num_vertices;j++)
9973                         {
9974                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9975                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9976                                 vi++;
9977                         }
9978                 }
9979                 R_Mesh_PrepareVertices_Generic_Unlock();
9980                 RSurf_DrawBatch();
9981         }
9982 }
9983
9984 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9985 {
9986         CHECKGLERROR
9987         RSurf_SetupDepthAndCulling();
9988         if (r_showsurfaces.integer)
9989         {
9990                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9991                 return;
9992         }
9993         switch (vid.renderpath)
9994         {
9995         case RENDERPATH_GL20:
9996         case RENDERPATH_D3D9:
9997         case RENDERPATH_D3D10:
9998         case RENDERPATH_D3D11:
9999         case RENDERPATH_SOFT:
10000         case RENDERPATH_GLES2:
10001                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10002                 break;
10003         case RENDERPATH_GL13:
10004         case RENDERPATH_GLES1:
10005                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10006                 break;
10007         case RENDERPATH_GL11:
10008                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10009                 break;
10010         }
10011         CHECKGLERROR
10012 }
10013
10014 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10015 {
10016         CHECKGLERROR
10017         RSurf_SetupDepthAndCulling();
10018         if (r_showsurfaces.integer)
10019         {
10020                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10021                 return;
10022         }
10023         switch (vid.renderpath)
10024         {
10025         case RENDERPATH_GL20:
10026         case RENDERPATH_D3D9:
10027         case RENDERPATH_D3D10:
10028         case RENDERPATH_D3D11:
10029         case RENDERPATH_SOFT:
10030         case RENDERPATH_GLES2:
10031                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10032                 break;
10033         case RENDERPATH_GL13:
10034         case RENDERPATH_GLES1:
10035                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10036                 break;
10037         case RENDERPATH_GL11:
10038                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10039                 break;
10040         }
10041         CHECKGLERROR
10042 }
10043
10044 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10045 {
10046         int i, j;
10047         int texturenumsurfaces, endsurface;
10048         texture_t *texture;
10049         const msurface_t *surface;
10050         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10051
10052         // if the model is static it doesn't matter what value we give for
10053         // wantnormals and wanttangents, so this logic uses only rules applicable
10054         // to a model, knowing that they are meaningless otherwise
10055         if (ent == r_refdef.scene.worldentity)
10056                 RSurf_ActiveWorldEntity();
10057         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10058                 RSurf_ActiveModelEntity(ent, false, false, false);
10059         else
10060         {
10061                 switch (vid.renderpath)
10062                 {
10063                 case RENDERPATH_GL20:
10064                 case RENDERPATH_D3D9:
10065                 case RENDERPATH_D3D10:
10066                 case RENDERPATH_D3D11:
10067                 case RENDERPATH_SOFT:
10068                 case RENDERPATH_GLES2:
10069                         RSurf_ActiveModelEntity(ent, true, true, false);
10070                         break;
10071                 case RENDERPATH_GL11:
10072                 case RENDERPATH_GL13:
10073                 case RENDERPATH_GLES1:
10074                         RSurf_ActiveModelEntity(ent, true, false, false);
10075                         break;
10076                 }
10077         }
10078
10079         if (r_transparentdepthmasking.integer)
10080         {
10081                 qboolean setup = false;
10082                 for (i = 0;i < numsurfaces;i = j)
10083                 {
10084                         j = i + 1;
10085                         surface = rsurface.modelsurfaces + surfacelist[i];
10086                         texture = surface->texture;
10087                         rsurface.texture = R_GetCurrentTexture(texture);
10088                         rsurface.lightmaptexture = NULL;
10089                         rsurface.deluxemaptexture = NULL;
10090                         rsurface.uselightmaptexture = false;
10091                         // scan ahead until we find a different texture
10092                         endsurface = min(i + 1024, numsurfaces);
10093                         texturenumsurfaces = 0;
10094                         texturesurfacelist[texturenumsurfaces++] = surface;
10095                         for (;j < endsurface;j++)
10096                         {
10097                                 surface = rsurface.modelsurfaces + surfacelist[j];
10098                                 if (texture != surface->texture)
10099                                         break;
10100                                 texturesurfacelist[texturenumsurfaces++] = surface;
10101                         }
10102                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10103                                 continue;
10104                         // render the range of surfaces as depth
10105                         if (!setup)
10106                         {
10107                                 setup = true;
10108                                 GL_ColorMask(0,0,0,0);
10109                                 GL_Color(1,1,1,1);
10110                                 GL_DepthTest(true);
10111                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10112                                 GL_DepthMask(true);
10113 //                              R_Mesh_ResetTextureState();
10114                                 R_SetupShader_DepthOrShadow();
10115                         }
10116                         RSurf_SetupDepthAndCulling();
10117                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10118                         if (rsurface.batchvertex3fbuffer)
10119                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10120                         else
10121                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10122                         RSurf_DrawBatch();
10123                 }
10124                 if (setup)
10125                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10126         }
10127
10128         for (i = 0;i < numsurfaces;i = j)
10129         {
10130                 j = i + 1;
10131                 surface = rsurface.modelsurfaces + surfacelist[i];
10132                 texture = surface->texture;
10133                 rsurface.texture = R_GetCurrentTexture(texture);
10134                 // scan ahead until we find a different texture
10135                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10136                 texturenumsurfaces = 0;
10137                 texturesurfacelist[texturenumsurfaces++] = surface;
10138                 if(FAKELIGHT_ENABLED)
10139                 {
10140                         rsurface.lightmaptexture = NULL;
10141                         rsurface.deluxemaptexture = NULL;
10142                         rsurface.uselightmaptexture = false;
10143                         for (;j < endsurface;j++)
10144                         {
10145                                 surface = rsurface.modelsurfaces + surfacelist[j];
10146                                 if (texture != surface->texture)
10147                                         break;
10148                                 texturesurfacelist[texturenumsurfaces++] = surface;
10149                         }
10150                 }
10151                 else
10152                 {
10153                         rsurface.lightmaptexture = surface->lightmaptexture;
10154                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10155                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10156                         for (;j < endsurface;j++)
10157                         {
10158                                 surface = rsurface.modelsurfaces + surfacelist[j];
10159                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10160                                         break;
10161                                 texturesurfacelist[texturenumsurfaces++] = surface;
10162                         }
10163                 }
10164                 // render the range of surfaces
10165                 if (ent == r_refdef.scene.worldentity)
10166                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10167                 else
10168                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10169         }
10170         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10171 }
10172
10173 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10174 {
10175         // transparent surfaces get pushed off into the transparent queue
10176         int surfacelistindex;
10177         const msurface_t *surface;
10178         vec3_t tempcenter, center;
10179         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10180         {
10181                 surface = texturesurfacelist[surfacelistindex];
10182                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10183                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10184                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10185                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10186                 if (queueentity->transparent_offset) // transparent offset
10187                 {
10188                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10189                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10190                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10191                 }
10192                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10193         }
10194 }
10195
10196 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10197 {
10198         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10199                 return;
10200         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10201                 return;
10202         RSurf_SetupDepthAndCulling();
10203         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10204         if (rsurface.batchvertex3fbuffer)
10205                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10206         else
10207                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10208         RSurf_DrawBatch();
10209 }
10210
10211 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10212 {
10213         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10214         CHECKGLERROR
10215         if (depthonly)
10216                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10217         else if (prepass)
10218         {
10219                 if (!rsurface.texture->currentnumlayers)
10220                         return;
10221                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10222                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10223                 else
10224                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10225         }
10226         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10227                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10228         else if (!rsurface.texture->currentnumlayers)
10229                 return;
10230         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10231         {
10232                 // in the deferred case, transparent surfaces were queued during prepass
10233                 if (!r_shadow_usingdeferredprepass)
10234                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10235         }
10236         else
10237         {
10238                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10239                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10240         }
10241         CHECKGLERROR
10242 }
10243
10244 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10245 {
10246         int i, j;
10247         texture_t *texture;
10248         R_FrameData_SetMark();
10249         // break the surface list down into batches by texture and use of lightmapping
10250         for (i = 0;i < numsurfaces;i = j)
10251         {
10252                 j = i + 1;
10253                 // texture is the base texture pointer, rsurface.texture is the
10254                 // current frame/skin the texture is directing us to use (for example
10255                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10256                 // use skin 1 instead)
10257                 texture = surfacelist[i]->texture;
10258                 rsurface.texture = R_GetCurrentTexture(texture);
10259                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10260                 {
10261                         // if this texture is not the kind we want, skip ahead to the next one
10262                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10263                                 ;
10264                         continue;
10265                 }
10266                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10267                 {
10268                         rsurface.lightmaptexture = NULL;
10269                         rsurface.deluxemaptexture = NULL;
10270                         rsurface.uselightmaptexture = false;
10271                         // simply scan ahead until we find a different texture or lightmap state
10272                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10273                                 ;
10274                 }
10275                 else
10276                 {
10277                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10278                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10279                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10280                         // simply scan ahead until we find a different texture or lightmap state
10281                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10282                                 ;
10283                 }
10284                 // render the range of surfaces
10285                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10286         }
10287         R_FrameData_ReturnToMark();
10288 }
10289
10290 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10291 {
10292         CHECKGLERROR
10293         if (depthonly)
10294                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10295         else if (prepass)
10296         {
10297                 if (!rsurface.texture->currentnumlayers)
10298                         return;
10299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10300                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10301                 else
10302                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10303         }
10304         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10305                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10306         else if (!rsurface.texture->currentnumlayers)
10307                 return;
10308         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10309         {
10310                 // in the deferred case, transparent surfaces were queued during prepass
10311                 if (!r_shadow_usingdeferredprepass)
10312                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10313         }
10314         else
10315         {
10316                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10317                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10318         }
10319         CHECKGLERROR
10320 }
10321
10322 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10323 {
10324         int i, j;
10325         texture_t *texture;
10326         R_FrameData_SetMark();
10327         // break the surface list down into batches by texture and use of lightmapping
10328         for (i = 0;i < numsurfaces;i = j)
10329         {
10330                 j = i + 1;
10331                 // texture is the base texture pointer, rsurface.texture is the
10332                 // current frame/skin the texture is directing us to use (for example
10333                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10334                 // use skin 1 instead)
10335                 texture = surfacelist[i]->texture;
10336                 rsurface.texture = R_GetCurrentTexture(texture);
10337                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10338                 {
10339                         // if this texture is not the kind we want, skip ahead to the next one
10340                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10341                                 ;
10342                         continue;
10343                 }
10344                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10345                 {
10346                         rsurface.lightmaptexture = NULL;
10347                         rsurface.deluxemaptexture = NULL;
10348                         rsurface.uselightmaptexture = false;
10349                         // simply scan ahead until we find a different texture or lightmap state
10350                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10351                                 ;
10352                 }
10353                 else
10354                 {
10355                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10356                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10357                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10358                         // simply scan ahead until we find a different texture or lightmap state
10359                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10360                                 ;
10361                 }
10362                 // render the range of surfaces
10363                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10364         }
10365         R_FrameData_ReturnToMark();
10366 }
10367
10368 float locboxvertex3f[6*4*3] =
10369 {
10370         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10371         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10372         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10373         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10374         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10375         1,0,0, 0,0,0, 0,1,0, 1,1,0
10376 };
10377
10378 unsigned short locboxelements[6*2*3] =
10379 {
10380          0, 1, 2, 0, 2, 3,
10381          4, 5, 6, 4, 6, 7,
10382          8, 9,10, 8,10,11,
10383         12,13,14, 12,14,15,
10384         16,17,18, 16,18,19,
10385         20,21,22, 20,22,23
10386 };
10387
10388 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10389 {
10390         int i, j;
10391         cl_locnode_t *loc = (cl_locnode_t *)ent;
10392         vec3_t mins, size;
10393         float vertex3f[6*4*3];
10394         CHECKGLERROR
10395         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10396         GL_DepthMask(false);
10397         GL_DepthRange(0, 1);
10398         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10399         GL_DepthTest(true);
10400         GL_CullFace(GL_NONE);
10401         R_EntityMatrix(&identitymatrix);
10402
10403 //      R_Mesh_ResetTextureState();
10404
10405         i = surfacelist[0];
10406         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10407                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10408                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10409                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10410
10411         if (VectorCompare(loc->mins, loc->maxs))
10412         {
10413                 VectorSet(size, 2, 2, 2);
10414                 VectorMA(loc->mins, -0.5f, size, mins);
10415         }
10416         else
10417         {
10418                 VectorCopy(loc->mins, mins);
10419                 VectorSubtract(loc->maxs, loc->mins, size);
10420         }
10421
10422         for (i = 0;i < 6*4*3;)
10423                 for (j = 0;j < 3;j++, i++)
10424                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10425
10426         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10427         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10428         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10429 }
10430
10431 void R_DrawLocs(void)
10432 {
10433         int index;
10434         cl_locnode_t *loc, *nearestloc;
10435         vec3_t center;
10436         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10437         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10438         {
10439                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10440                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10441         }
10442 }
10443
10444 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10445 {
10446         if (decalsystem->decals)
10447                 Mem_Free(decalsystem->decals);
10448         memset(decalsystem, 0, sizeof(*decalsystem));
10449 }
10450
10451 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)
10452 {
10453         tridecal_t *decal;
10454         tridecal_t *decals;
10455         int i;
10456
10457         // expand or initialize the system
10458         if (decalsystem->maxdecals <= decalsystem->numdecals)
10459         {
10460                 decalsystem_t old = *decalsystem;
10461                 qboolean useshortelements;
10462                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10463                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10464                 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)));
10465                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10466                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10467                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10468                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10469                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10470                 if (decalsystem->numdecals)
10471                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10472                 if (old.decals)
10473                         Mem_Free(old.decals);
10474                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10475                         decalsystem->element3i[i] = i;
10476                 if (useshortelements)
10477                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10478                                 decalsystem->element3s[i] = i;
10479         }
10480
10481         // grab a decal and search for another free slot for the next one
10482         decals = decalsystem->decals;
10483         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10484         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10485                 ;
10486         decalsystem->freedecal = i;
10487         if (decalsystem->numdecals <= i)
10488                 decalsystem->numdecals = i + 1;
10489
10490         // initialize the decal
10491         decal->lived = 0;
10492         decal->triangleindex = triangleindex;
10493         decal->surfaceindex = surfaceindex;
10494         decal->decalsequence = decalsequence;
10495         decal->color4f[0][0] = c0[0];
10496         decal->color4f[0][1] = c0[1];
10497         decal->color4f[0][2] = c0[2];
10498         decal->color4f[0][3] = 1;
10499         decal->color4f[1][0] = c1[0];
10500         decal->color4f[1][1] = c1[1];
10501         decal->color4f[1][2] = c1[2];
10502         decal->color4f[1][3] = 1;
10503         decal->color4f[2][0] = c2[0];
10504         decal->color4f[2][1] = c2[1];
10505         decal->color4f[2][2] = c2[2];
10506         decal->color4f[2][3] = 1;
10507         decal->vertex3f[0][0] = v0[0];
10508         decal->vertex3f[0][1] = v0[1];
10509         decal->vertex3f[0][2] = v0[2];
10510         decal->vertex3f[1][0] = v1[0];
10511         decal->vertex3f[1][1] = v1[1];
10512         decal->vertex3f[1][2] = v1[2];
10513         decal->vertex3f[2][0] = v2[0];
10514         decal->vertex3f[2][1] = v2[1];
10515         decal->vertex3f[2][2] = v2[2];
10516         decal->texcoord2f[0][0] = t0[0];
10517         decal->texcoord2f[0][1] = t0[1];
10518         decal->texcoord2f[1][0] = t1[0];
10519         decal->texcoord2f[1][1] = t1[1];
10520         decal->texcoord2f[2][0] = t2[0];
10521         decal->texcoord2f[2][1] = t2[1];
10522         TriangleNormal(v0, v1, v2, decal->plane);
10523         VectorNormalize(decal->plane);
10524         decal->plane[3] = DotProduct(v0, decal->plane);
10525 }
10526
10527 extern cvar_t cl_decals_bias;
10528 extern cvar_t cl_decals_models;
10529 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10530 // baseparms, parms, temps
10531 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)
10532 {
10533         int cornerindex;
10534         int index;
10535         float v[9][3];
10536         const float *vertex3f;
10537         const float *normal3f;
10538         int numpoints;
10539         float points[2][9][3];
10540         float temp[3];
10541         float tc[9][2];
10542         float f;
10543         float c[9][4];
10544         const int *e;
10545
10546         e = rsurface.modelelement3i + 3*triangleindex;
10547
10548         vertex3f = rsurface.modelvertex3f;
10549         normal3f = rsurface.modelnormal3f;
10550
10551         if (normal3f)
10552         {
10553                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10554                 {
10555                         index = 3*e[cornerindex];
10556                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10557                 }
10558         }
10559         else
10560         {
10561                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10562                 {
10563                         index = 3*e[cornerindex];
10564                         VectorCopy(vertex3f + index, v[cornerindex]);
10565                 }
10566         }
10567
10568         // cull backfaces
10569         //TriangleNormal(v[0], v[1], v[2], normal);
10570         //if (DotProduct(normal, localnormal) < 0.0f)
10571         //      continue;
10572         // clip by each of the box planes formed from the projection matrix
10573         // if anything survives, we emit the decal
10574         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]);
10575         if (numpoints < 3)
10576                 return;
10577         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]);
10578         if (numpoints < 3)
10579                 return;
10580         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]);
10581         if (numpoints < 3)
10582                 return;
10583         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]);
10584         if (numpoints < 3)
10585                 return;
10586         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]);
10587         if (numpoints < 3)
10588                 return;
10589         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]);
10590         if (numpoints < 3)
10591                 return;
10592         // some part of the triangle survived, so we have to accept it...
10593         if (dynamic)
10594         {
10595                 // dynamic always uses the original triangle
10596                 numpoints = 3;
10597                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10598                 {
10599                         index = 3*e[cornerindex];
10600                         VectorCopy(vertex3f + index, v[cornerindex]);
10601                 }
10602         }
10603         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10604         {
10605                 // convert vertex positions to texcoords
10606                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10607                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10608                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10609                 // calculate distance fade from the projection origin
10610                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10611                 f = bound(0.0f, f, 1.0f);
10612                 c[cornerindex][0] = r * f;
10613                 c[cornerindex][1] = g * f;
10614                 c[cornerindex][2] = b * f;
10615                 c[cornerindex][3] = 1.0f;
10616                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10617         }
10618         if (dynamic)
10619                 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);
10620         else
10621                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10622                         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);
10623 }
10624 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)
10625 {
10626         matrix4x4_t projection;
10627         decalsystem_t *decalsystem;
10628         qboolean dynamic;
10629         dp_model_t *model;
10630         const msurface_t *surface;
10631         const msurface_t *surfaces;
10632         const int *surfacelist;
10633         const texture_t *texture;
10634         int numtriangles;
10635         int numsurfacelist;
10636         int surfacelistindex;
10637         int surfaceindex;
10638         int triangleindex;
10639         float localorigin[3];
10640         float localnormal[3];
10641         float localmins[3];
10642         float localmaxs[3];
10643         float localsize;
10644         //float normal[3];
10645         float planes[6][4];
10646         float angles[3];
10647         bih_t *bih;
10648         int bih_triangles_count;
10649         int bih_triangles[256];
10650         int bih_surfaces[256];
10651
10652         decalsystem = &ent->decalsystem;
10653         model = ent->model;
10654         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10655         {
10656                 R_DecalSystem_Reset(&ent->decalsystem);
10657                 return;
10658         }
10659
10660         if (!model->brush.data_leafs && !cl_decals_models.integer)
10661         {
10662                 if (decalsystem->model)
10663                         R_DecalSystem_Reset(decalsystem);
10664                 return;
10665         }
10666
10667         if (decalsystem->model != model)
10668                 R_DecalSystem_Reset(decalsystem);
10669         decalsystem->model = model;
10670
10671         RSurf_ActiveModelEntity(ent, true, false, false);
10672
10673         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10674         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10675         VectorNormalize(localnormal);
10676         localsize = worldsize*rsurface.inversematrixscale;
10677         localmins[0] = localorigin[0] - localsize;
10678         localmins[1] = localorigin[1] - localsize;
10679         localmins[2] = localorigin[2] - localsize;
10680         localmaxs[0] = localorigin[0] + localsize;
10681         localmaxs[1] = localorigin[1] + localsize;
10682         localmaxs[2] = localorigin[2] + localsize;
10683
10684         //VectorCopy(localnormal, planes[4]);
10685         //VectorVectors(planes[4], planes[2], planes[0]);
10686         AnglesFromVectors(angles, localnormal, NULL, false);
10687         AngleVectors(angles, planes[0], planes[2], planes[4]);
10688         VectorNegate(planes[0], planes[1]);
10689         VectorNegate(planes[2], planes[3]);
10690         VectorNegate(planes[4], planes[5]);
10691         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10692         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10693         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10694         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10695         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10696         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10697
10698 #if 1
10699 // works
10700 {
10701         matrix4x4_t forwardprojection;
10702         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10703         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10704 }
10705 #else
10706 // broken
10707 {
10708         float projectionvector[4][3];
10709         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10710         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10711         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10712         projectionvector[0][0] = planes[0][0] * ilocalsize;
10713         projectionvector[0][1] = planes[1][0] * ilocalsize;
10714         projectionvector[0][2] = planes[2][0] * ilocalsize;
10715         projectionvector[1][0] = planes[0][1] * ilocalsize;
10716         projectionvector[1][1] = planes[1][1] * ilocalsize;
10717         projectionvector[1][2] = planes[2][1] * ilocalsize;
10718         projectionvector[2][0] = planes[0][2] * ilocalsize;
10719         projectionvector[2][1] = planes[1][2] * ilocalsize;
10720         projectionvector[2][2] = planes[2][2] * ilocalsize;
10721         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10722         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10723         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10724         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10725 }
10726 #endif
10727
10728         dynamic = model->surfmesh.isanimated;
10729         numsurfacelist = model->nummodelsurfaces;
10730         surfacelist = model->sortedmodelsurfaces;
10731         surfaces = model->data_surfaces;
10732
10733         bih = NULL;
10734         bih_triangles_count = -1;
10735         if(!dynamic)
10736         {
10737                 if(model->render_bih.numleafs)
10738                         bih = &model->render_bih;
10739                 else if(model->collision_bih.numleafs)
10740                         bih = &model->collision_bih;
10741         }
10742         if(bih)
10743                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10744         if(bih_triangles_count == 0)
10745                 return;
10746         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10747                 return;
10748         if(bih_triangles_count > 0)
10749         {
10750                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10751                 {
10752                         surfaceindex = bih_surfaces[triangleindex];
10753                         surface = surfaces + surfaceindex;
10754                         texture = surface->texture;
10755                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10756                                 continue;
10757                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10758                                 continue;
10759                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10760                 }
10761         }
10762         else
10763         {
10764                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10765                 {
10766                         surfaceindex = surfacelist[surfacelistindex];
10767                         surface = surfaces + surfaceindex;
10768                         // check cull box first because it rejects more than any other check
10769                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10770                                 continue;
10771                         // skip transparent surfaces
10772                         texture = surface->texture;
10773                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10774                                 continue;
10775                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10776                                 continue;
10777                         numtriangles = surface->num_triangles;
10778                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10779                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10780                 }
10781         }
10782 }
10783
10784 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10785 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)
10786 {
10787         int renderentityindex;
10788         float worldmins[3];
10789         float worldmaxs[3];
10790         entity_render_t *ent;
10791
10792         if (!cl_decals_newsystem.integer)
10793                 return;
10794
10795         worldmins[0] = worldorigin[0] - worldsize;
10796         worldmins[1] = worldorigin[1] - worldsize;
10797         worldmins[2] = worldorigin[2] - worldsize;
10798         worldmaxs[0] = worldorigin[0] + worldsize;
10799         worldmaxs[1] = worldorigin[1] + worldsize;
10800         worldmaxs[2] = worldorigin[2] + worldsize;
10801
10802         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10803
10804         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10805         {
10806                 ent = r_refdef.scene.entities[renderentityindex];
10807                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10808                         continue;
10809
10810                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10811         }
10812 }
10813
10814 typedef struct r_decalsystem_splatqueue_s
10815 {
10816         vec3_t worldorigin;
10817         vec3_t worldnormal;
10818         float color[4];
10819         float tcrange[4];
10820         float worldsize;
10821         int decalsequence;
10822 }
10823 r_decalsystem_splatqueue_t;
10824
10825 int r_decalsystem_numqueued = 0;
10826 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10827
10828 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)
10829 {
10830         r_decalsystem_splatqueue_t *queue;
10831
10832         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10833                 return;
10834
10835         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10836         VectorCopy(worldorigin, queue->worldorigin);
10837         VectorCopy(worldnormal, queue->worldnormal);
10838         Vector4Set(queue->color, r, g, b, a);
10839         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10840         queue->worldsize = worldsize;
10841         queue->decalsequence = cl.decalsequence++;
10842 }
10843
10844 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10845 {
10846         int i;
10847         r_decalsystem_splatqueue_t *queue;
10848
10849         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10850                 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);
10851         r_decalsystem_numqueued = 0;
10852 }
10853
10854 extern cvar_t cl_decals_max;
10855 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10856 {
10857         int i;
10858         decalsystem_t *decalsystem = &ent->decalsystem;
10859         int numdecals;
10860         int killsequence;
10861         tridecal_t *decal;
10862         float frametime;
10863         float lifetime;
10864
10865         if (!decalsystem->numdecals)
10866                 return;
10867
10868         if (r_showsurfaces.integer)
10869                 return;
10870
10871         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10872         {
10873                 R_DecalSystem_Reset(decalsystem);
10874                 return;
10875         }
10876
10877         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10878         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10879
10880         if (decalsystem->lastupdatetime)
10881                 frametime = (cl.time - decalsystem->lastupdatetime);
10882         else
10883                 frametime = 0;
10884         decalsystem->lastupdatetime = cl.time;
10885         decal = decalsystem->decals;
10886         numdecals = decalsystem->numdecals;
10887
10888         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10889         {
10890                 if (decal->color4f[0][3])
10891                 {
10892                         decal->lived += frametime;
10893                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10894                         {
10895                                 memset(decal, 0, sizeof(*decal));
10896                                 if (decalsystem->freedecal > i)
10897                                         decalsystem->freedecal = i;
10898                         }
10899                 }
10900         }
10901         decal = decalsystem->decals;
10902         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10903                 numdecals--;
10904
10905         // collapse the array by shuffling the tail decals into the gaps
10906         for (;;)
10907         {
10908                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10909                         decalsystem->freedecal++;
10910                 if (decalsystem->freedecal == numdecals)
10911                         break;
10912                 decal[decalsystem->freedecal] = decal[--numdecals];
10913         }
10914
10915         decalsystem->numdecals = numdecals;
10916
10917         if (numdecals <= 0)
10918         {
10919                 // if there are no decals left, reset decalsystem
10920                 R_DecalSystem_Reset(decalsystem);
10921         }
10922 }
10923
10924 extern skinframe_t *decalskinframe;
10925 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10926 {
10927         int i;
10928         decalsystem_t *decalsystem = &ent->decalsystem;
10929         int numdecals;
10930         tridecal_t *decal;
10931         float faderate;
10932         float alpha;
10933         float *v3f;
10934         float *c4f;
10935         float *t2f;
10936         const int *e;
10937         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10938         int numtris = 0;
10939
10940         numdecals = decalsystem->numdecals;
10941         if (!numdecals)
10942                 return;
10943
10944         if (r_showsurfaces.integer)
10945                 return;
10946
10947         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10948         {
10949                 R_DecalSystem_Reset(decalsystem);
10950                 return;
10951         }
10952
10953         // if the model is static it doesn't matter what value we give for
10954         // wantnormals and wanttangents, so this logic uses only rules applicable
10955         // to a model, knowing that they are meaningless otherwise
10956         if (ent == r_refdef.scene.worldentity)
10957                 RSurf_ActiveWorldEntity();
10958         else
10959                 RSurf_ActiveModelEntity(ent, false, false, false);
10960
10961         decalsystem->lastupdatetime = cl.time;
10962         decal = decalsystem->decals;
10963
10964         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10965
10966         // update vertex positions for animated models
10967         v3f = decalsystem->vertex3f;
10968         c4f = decalsystem->color4f;
10969         t2f = decalsystem->texcoord2f;
10970         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10971         {
10972                 if (!decal->color4f[0][3])
10973                         continue;
10974
10975                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10976                         continue;
10977
10978                 // skip backfaces
10979                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10980                         continue;
10981
10982                 // update color values for fading decals
10983                 if (decal->lived >= cl_decals_time.value)
10984                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10985                 else
10986                         alpha = 1.0f;
10987
10988                 c4f[ 0] = decal->color4f[0][0] * alpha;
10989                 c4f[ 1] = decal->color4f[0][1] * alpha;
10990                 c4f[ 2] = decal->color4f[0][2] * alpha;
10991                 c4f[ 3] = 1;
10992                 c4f[ 4] = decal->color4f[1][0] * alpha;
10993                 c4f[ 5] = decal->color4f[1][1] * alpha;
10994                 c4f[ 6] = decal->color4f[1][2] * alpha;
10995                 c4f[ 7] = 1;
10996                 c4f[ 8] = decal->color4f[2][0] * alpha;
10997                 c4f[ 9] = decal->color4f[2][1] * alpha;
10998                 c4f[10] = decal->color4f[2][2] * alpha;
10999                 c4f[11] = 1;
11000
11001                 t2f[0] = decal->texcoord2f[0][0];
11002                 t2f[1] = decal->texcoord2f[0][1];
11003                 t2f[2] = decal->texcoord2f[1][0];
11004                 t2f[3] = decal->texcoord2f[1][1];
11005                 t2f[4] = decal->texcoord2f[2][0];
11006                 t2f[5] = decal->texcoord2f[2][1];
11007
11008                 // update vertex positions for animated models
11009                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11010                 {
11011                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11012                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11013                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11014                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11015                 }
11016                 else
11017                 {
11018                         VectorCopy(decal->vertex3f[0], v3f);
11019                         VectorCopy(decal->vertex3f[1], v3f + 3);
11020                         VectorCopy(decal->vertex3f[2], v3f + 6);
11021                 }
11022
11023                 if (r_refdef.fogenabled)
11024                 {
11025                         alpha = RSurf_FogVertex(v3f);
11026                         VectorScale(c4f, alpha, c4f);
11027                         alpha = RSurf_FogVertex(v3f + 3);
11028                         VectorScale(c4f + 4, alpha, c4f + 4);
11029                         alpha = RSurf_FogVertex(v3f + 6);
11030                         VectorScale(c4f + 8, alpha, c4f + 8);
11031                 }
11032
11033                 v3f += 9;
11034                 c4f += 12;
11035                 t2f += 6;
11036                 numtris++;
11037         }
11038
11039         if (numtris > 0)
11040         {
11041                 r_refdef.stats.drawndecals += numtris;
11042
11043                 // now render the decals all at once
11044                 // (this assumes they all use one particle font texture!)
11045                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11046 //              R_Mesh_ResetTextureState();
11047                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11048                 GL_DepthMask(false);
11049                 GL_DepthRange(0, 1);
11050                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11051                 GL_DepthTest(true);
11052                 GL_CullFace(GL_NONE);
11053                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11054                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11055                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11056         }
11057 }
11058
11059 static void R_DrawModelDecals(void)
11060 {
11061         int i, numdecals;
11062
11063         // fade faster when there are too many decals
11064         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11065         for (i = 0;i < r_refdef.scene.numentities;i++)
11066                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11067
11068         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11069         for (i = 0;i < r_refdef.scene.numentities;i++)
11070                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11071                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11072
11073         R_DecalSystem_ApplySplatEntitiesQueue();
11074
11075         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11076         for (i = 0;i < r_refdef.scene.numentities;i++)
11077                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11078
11079         r_refdef.stats.totaldecals += numdecals;
11080
11081         if (r_showsurfaces.integer)
11082                 return;
11083
11084         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11085
11086         for (i = 0;i < r_refdef.scene.numentities;i++)
11087         {
11088                 if (!r_refdef.viewcache.entityvisible[i])
11089                         continue;
11090                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11091                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11092         }
11093 }
11094
11095 extern cvar_t mod_collision_bih;
11096 void R_DrawDebugModel(void)
11097 {
11098         entity_render_t *ent = rsurface.entity;
11099         int i, j, k, l, flagsmask;
11100         const msurface_t *surface;
11101         dp_model_t *model = ent->model;
11102         vec3_t v;
11103
11104         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11105                 return;
11106
11107         if (r_showoverdraw.value > 0)
11108         {
11109                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11110                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11111                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11112                 GL_DepthTest(false);
11113                 GL_DepthMask(false);
11114                 GL_DepthRange(0, 1);
11115                 GL_BlendFunc(GL_ONE, GL_ONE);
11116                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11117                 {
11118                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11119                                 continue;
11120                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11121                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11122                         {
11123                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11124                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11125                                 if (!rsurface.texture->currentlayers->depthmask)
11126                                         GL_Color(c, 0, 0, 1.0f);
11127                                 else if (ent == r_refdef.scene.worldentity)
11128                                         GL_Color(c, c, c, 1.0f);
11129                                 else
11130                                         GL_Color(0, c, 0, 1.0f);
11131                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11132                                 RSurf_DrawBatch();
11133                         }
11134                 }
11135                 rsurface.texture = NULL;
11136         }
11137
11138         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11139
11140 //      R_Mesh_ResetTextureState();
11141         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11142         GL_DepthRange(0, 1);
11143         GL_DepthTest(!r_showdisabledepthtest.integer);
11144         GL_DepthMask(false);
11145         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11146
11147         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11148         {
11149                 int triangleindex;
11150                 int bihleafindex;
11151                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11152                 const q3mbrush_t *brush;
11153                 const bih_t *bih = &model->collision_bih;
11154                 const bih_leaf_t *bihleaf;
11155                 float vertex3f[3][3];
11156                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11157                 cullbox = false;
11158                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11159                 {
11160                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11161                                 continue;
11162                         switch (bihleaf->type)
11163                         {
11164                         case BIH_BRUSH:
11165                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11166                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11167                                 {
11168                                         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);
11169                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11170                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11171                                 }
11172                                 break;
11173                         case BIH_COLLISIONTRIANGLE:
11174                                 triangleindex = bihleaf->itemindex;
11175                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11176                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11177                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11178                                 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);
11179                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11180                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11181                                 break;
11182                         case BIH_RENDERTRIANGLE:
11183                                 triangleindex = bihleaf->itemindex;
11184                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11185                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11186                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11187                                 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);
11188                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11189                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11190                                 break;
11191                         }
11192                 }
11193         }
11194
11195         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11196
11197         if (r_showtris.integer && qglPolygonMode)
11198         {
11199                 if (r_showdisabledepthtest.integer)
11200                 {
11201                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11202                         GL_DepthMask(false);
11203                 }
11204                 else
11205                 {
11206                         GL_BlendFunc(GL_ONE, GL_ZERO);
11207                         GL_DepthMask(true);
11208                 }
11209                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11210                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11211                 {
11212                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11213                                 continue;
11214                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11215                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11216                         {
11217                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11218                                 if (!rsurface.texture->currentlayers->depthmask)
11219                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11220                                 else if (ent == r_refdef.scene.worldentity)
11221                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11222                                 else
11223                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11224                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11225                                 RSurf_DrawBatch();
11226                         }
11227                 }
11228                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11229                 rsurface.texture = NULL;
11230         }
11231
11232         if (r_shownormals.value != 0 && qglBegin)
11233         {
11234                 if (r_showdisabledepthtest.integer)
11235                 {
11236                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11237                         GL_DepthMask(false);
11238                 }
11239                 else
11240                 {
11241                         GL_BlendFunc(GL_ONE, GL_ZERO);
11242                         GL_DepthMask(true);
11243                 }
11244                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11245                 {
11246                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11247                                 continue;
11248                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11249                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11250                         {
11251                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11252                                 qglBegin(GL_LINES);
11253                                 if (r_shownormals.value < 0)
11254                                 {
11255                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11256                                         {
11257                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11258                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11259                                                 qglVertex3f(v[0], v[1], v[2]);
11260                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11261                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11262                                                 qglVertex3f(v[0], v[1], v[2]);
11263                                         }
11264                                 }
11265                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11266                                 {
11267                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11268                                         {
11269                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11270                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11271                                                 qglVertex3f(v[0], v[1], v[2]);
11272                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11273                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11274                                                 qglVertex3f(v[0], v[1], v[2]);
11275                                         }
11276                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11277                                         {
11278                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11279                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11280                                                 qglVertex3f(v[0], v[1], v[2]);
11281                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11282                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11283                                                 qglVertex3f(v[0], v[1], v[2]);
11284                                         }
11285                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11286                                         {
11287                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11288                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11289                                                 qglVertex3f(v[0], v[1], v[2]);
11290                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11291                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11292                                                 qglVertex3f(v[0], v[1], v[2]);
11293                                         }
11294                                 }
11295                                 qglEnd();
11296                                 CHECKGLERROR
11297                         }
11298                 }
11299                 rsurface.texture = NULL;
11300         }
11301 }
11302
11303 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11304 int r_maxsurfacelist = 0;
11305 const msurface_t **r_surfacelist = NULL;
11306 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11307 {
11308         int i, j, endj, flagsmask;
11309         dp_model_t *model = r_refdef.scene.worldmodel;
11310         msurface_t *surfaces;
11311         unsigned char *update;
11312         int numsurfacelist = 0;
11313         if (model == NULL)
11314                 return;
11315
11316         if (r_maxsurfacelist < model->num_surfaces)
11317         {
11318                 r_maxsurfacelist = model->num_surfaces;
11319                 if (r_surfacelist)
11320                         Mem_Free((msurface_t**)r_surfacelist);
11321                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11322         }
11323
11324         RSurf_ActiveWorldEntity();
11325
11326         surfaces = model->data_surfaces;
11327         update = model->brushq1.lightmapupdateflags;
11328
11329         // update light styles on this submodel
11330         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11331         {
11332                 model_brush_lightstyleinfo_t *style;
11333                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11334                 {
11335                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11336                         {
11337                                 int *list = style->surfacelist;
11338                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11339                                 for (j = 0;j < style->numsurfaces;j++)
11340                                         update[list[j]] = true;
11341                         }
11342                 }
11343         }
11344
11345         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11346
11347         if (debug)
11348         {
11349                 R_DrawDebugModel();
11350                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11351                 return;
11352         }
11353
11354         rsurface.lightmaptexture = NULL;
11355         rsurface.deluxemaptexture = NULL;
11356         rsurface.uselightmaptexture = false;
11357         rsurface.texture = NULL;
11358         rsurface.rtlight = NULL;
11359         numsurfacelist = 0;
11360         // add visible surfaces to draw list
11361         for (i = 0;i < model->nummodelsurfaces;i++)
11362         {
11363                 j = model->sortedmodelsurfaces[i];
11364                 if (r_refdef.viewcache.world_surfacevisible[j])
11365                         r_surfacelist[numsurfacelist++] = surfaces + j;
11366         }
11367         // update lightmaps if needed
11368         if (model->brushq1.firstrender)
11369         {
11370                 model->brushq1.firstrender = false;
11371                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11372                         if (update[j])
11373                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11374         }
11375         else if (update)
11376         {
11377                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11378                         if (r_refdef.viewcache.world_surfacevisible[j])
11379                                 if (update[j])
11380                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11381         }
11382         // don't do anything if there were no surfaces
11383         if (!numsurfacelist)
11384         {
11385                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11386                 return;
11387         }
11388         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11389
11390         // add to stats if desired
11391         if (r_speeds.integer && !skysurfaces && !depthonly)
11392         {
11393                 r_refdef.stats.world_surfaces += numsurfacelist;
11394                 for (j = 0;j < numsurfacelist;j++)
11395                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11396         }
11397
11398         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11399 }
11400
11401 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11402 {
11403         int i, j, endj, flagsmask;
11404         dp_model_t *model = ent->model;
11405         msurface_t *surfaces;
11406         unsigned char *update;
11407         int numsurfacelist = 0;
11408         if (model == NULL)
11409                 return;
11410
11411         if (r_maxsurfacelist < model->num_surfaces)
11412         {
11413                 r_maxsurfacelist = model->num_surfaces;
11414                 if (r_surfacelist)
11415                         Mem_Free((msurface_t **)r_surfacelist);
11416                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11417         }
11418
11419         // if the model is static it doesn't matter what value we give for
11420         // wantnormals and wanttangents, so this logic uses only rules applicable
11421         // to a model, knowing that they are meaningless otherwise
11422         if (ent == r_refdef.scene.worldentity)
11423                 RSurf_ActiveWorldEntity();
11424         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11425                 RSurf_ActiveModelEntity(ent, false, false, false);
11426         else if (prepass)
11427                 RSurf_ActiveModelEntity(ent, true, true, true);
11428         else if (depthonly)
11429         {
11430                 switch (vid.renderpath)
11431                 {
11432                 case RENDERPATH_GL20:
11433                 case RENDERPATH_D3D9:
11434                 case RENDERPATH_D3D10:
11435                 case RENDERPATH_D3D11:
11436                 case RENDERPATH_SOFT:
11437                 case RENDERPATH_GLES2:
11438                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11439                         break;
11440                 case RENDERPATH_GL11:
11441                 case RENDERPATH_GL13:
11442                 case RENDERPATH_GLES1:
11443                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11444                         break;
11445                 }
11446         }
11447         else
11448         {
11449                 switch (vid.renderpath)
11450                 {
11451                 case RENDERPATH_GL20:
11452                 case RENDERPATH_D3D9:
11453                 case RENDERPATH_D3D10:
11454                 case RENDERPATH_D3D11:
11455                 case RENDERPATH_SOFT:
11456                 case RENDERPATH_GLES2:
11457                         RSurf_ActiveModelEntity(ent, true, true, false);
11458                         break;
11459                 case RENDERPATH_GL11:
11460                 case RENDERPATH_GL13:
11461                 case RENDERPATH_GLES1:
11462                         RSurf_ActiveModelEntity(ent, true, false, false);
11463                         break;
11464                 }
11465         }
11466
11467         surfaces = model->data_surfaces;
11468         update = model->brushq1.lightmapupdateflags;
11469
11470         // update light styles
11471         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11472         {
11473                 model_brush_lightstyleinfo_t *style;
11474                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11475                 {
11476                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11477                         {
11478                                 int *list = style->surfacelist;
11479                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11480                                 for (j = 0;j < style->numsurfaces;j++)
11481                                         update[list[j]] = true;
11482                         }
11483                 }
11484         }
11485
11486         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11487
11488         if (debug)
11489         {
11490                 R_DrawDebugModel();
11491                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11492                 return;
11493         }
11494
11495         rsurface.lightmaptexture = NULL;
11496         rsurface.deluxemaptexture = NULL;
11497         rsurface.uselightmaptexture = false;
11498         rsurface.texture = NULL;
11499         rsurface.rtlight = NULL;
11500         numsurfacelist = 0;
11501         // add visible surfaces to draw list
11502         for (i = 0;i < model->nummodelsurfaces;i++)
11503                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11504         // don't do anything if there were no surfaces
11505         if (!numsurfacelist)
11506         {
11507                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11508                 return;
11509         }
11510         // update lightmaps if needed
11511         if (update)
11512         {
11513                 int updated = 0;
11514                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11515                 {
11516                         if (update[j])
11517                         {
11518                                 updated++;
11519                                 R_BuildLightMap(ent, surfaces + j);
11520                         }
11521                 }
11522         }
11523         if (update)
11524                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11525                         if (update[j])
11526                                 R_BuildLightMap(ent, surfaces + j);
11527         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11528
11529         // add to stats if desired
11530         if (r_speeds.integer && !skysurfaces && !depthonly)
11531         {
11532                 r_refdef.stats.entities_surfaces += numsurfacelist;
11533                 for (j = 0;j < numsurfacelist;j++)
11534                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11535         }
11536
11537         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11538 }
11539
11540 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11541 {
11542         static texture_t texture;
11543         static msurface_t surface;
11544         const msurface_t *surfacelist = &surface;
11545
11546         // fake enough texture and surface state to render this geometry
11547
11548         texture.update_lastrenderframe = -1; // regenerate this texture
11549         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11550         texture.currentskinframe = skinframe;
11551         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11552         texture.offsetmapping = OFFSETMAPPING_OFF;
11553         texture.offsetscale = 1;
11554         texture.specularscalemod = 1;
11555         texture.specularpowermod = 1;
11556
11557         surface.texture = &texture;
11558         surface.num_triangles = numtriangles;
11559         surface.num_firsttriangle = firsttriangle;
11560         surface.num_vertices = numvertices;
11561         surface.num_firstvertex = firstvertex;
11562
11563         // now render it
11564         rsurface.texture = R_GetCurrentTexture(surface.texture);
11565         rsurface.lightmaptexture = NULL;
11566         rsurface.deluxemaptexture = NULL;
11567         rsurface.uselightmaptexture = false;
11568         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11569 }
11570
11571 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)
11572 {
11573         static msurface_t surface;
11574         const msurface_t *surfacelist = &surface;
11575
11576         // fake enough texture and surface state to render this geometry
11577         surface.texture = texture;
11578         surface.num_triangles = numtriangles;
11579         surface.num_firsttriangle = firsttriangle;
11580         surface.num_vertices = numvertices;
11581         surface.num_firstvertex = firstvertex;
11582
11583         // now render it
11584         rsurface.texture = R_GetCurrentTexture(surface.texture);
11585         rsurface.lightmaptexture = NULL;
11586         rsurface.deluxemaptexture = NULL;
11587         rsurface.uselightmaptexture = false;
11588         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11589 }