]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
honor ent->shadertime in all material handling (tcmod, etc)
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "0", "enables alpha-to-coverage antialiasing technique on alphatest surfaces, this is not yet finished as multisampling is not used"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
212
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
214
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673 };
674
675 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
676 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
677 {
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
680         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 };
695
696 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
697 {
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
714 };
715
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
718 {
719         /// hash lookup data
720         struct r_glsl_permutation_s *hashnext;
721         unsigned int mode;
722         unsigned int permutation;
723
724         /// indicates if we have tried compiling this permutation already
725         qboolean compiled;
726         /// 0 if compilation failed
727         int program;
728         // texture units assigned to each detected uniform
729         int tex_Texture_First;
730         int tex_Texture_Second;
731         int tex_Texture_GammaRamps;
732         int tex_Texture_Normal;
733         int tex_Texture_Color;
734         int tex_Texture_Gloss;
735         int tex_Texture_Glow;
736         int tex_Texture_SecondaryNormal;
737         int tex_Texture_SecondaryColor;
738         int tex_Texture_SecondaryGloss;
739         int tex_Texture_SecondaryGlow;
740         int tex_Texture_Pants;
741         int tex_Texture_Shirt;
742         int tex_Texture_FogHeightTexture;
743         int tex_Texture_FogMask;
744         int tex_Texture_Lightmap;
745         int tex_Texture_Deluxemap;
746         int tex_Texture_Attenuation;
747         int tex_Texture_Cube;
748         int tex_Texture_Refraction;
749         int tex_Texture_Reflection;
750         int tex_Texture_ShadowMap2D;
751         int tex_Texture_CubeProjection;
752         int tex_Texture_ScreenDepth;
753         int tex_Texture_ScreenNormalMap;
754         int tex_Texture_ScreenDiffuse;
755         int tex_Texture_ScreenSpecular;
756         int tex_Texture_ReflectMask;
757         int tex_Texture_ReflectCube;
758         int tex_Texture_BounceGrid;
759         /// locations of detected uniforms in program object, or -1 if not found
760         int loc_Texture_First;
761         int loc_Texture_Second;
762         int loc_Texture_GammaRamps;
763         int loc_Texture_Normal;
764         int loc_Texture_Color;
765         int loc_Texture_Gloss;
766         int loc_Texture_Glow;
767         int loc_Texture_SecondaryNormal;
768         int loc_Texture_SecondaryColor;
769         int loc_Texture_SecondaryGloss;
770         int loc_Texture_SecondaryGlow;
771         int loc_Texture_Pants;
772         int loc_Texture_Shirt;
773         int loc_Texture_FogHeightTexture;
774         int loc_Texture_FogMask;
775         int loc_Texture_Lightmap;
776         int loc_Texture_Deluxemap;
777         int loc_Texture_Attenuation;
778         int loc_Texture_Cube;
779         int loc_Texture_Refraction;
780         int loc_Texture_Reflection;
781         int loc_Texture_ShadowMap2D;
782         int loc_Texture_CubeProjection;
783         int loc_Texture_ScreenDepth;
784         int loc_Texture_ScreenNormalMap;
785         int loc_Texture_ScreenDiffuse;
786         int loc_Texture_ScreenSpecular;
787         int loc_Texture_ReflectMask;
788         int loc_Texture_ReflectCube;
789         int loc_Texture_BounceGrid;
790         int loc_Alpha;
791         int loc_BloomBlur_Parameters;
792         int loc_ClientTime;
793         int loc_Color_Ambient;
794         int loc_Color_Diffuse;
795         int loc_Color_Specular;
796         int loc_Color_Glow;
797         int loc_Color_Pants;
798         int loc_Color_Shirt;
799         int loc_DeferredColor_Ambient;
800         int loc_DeferredColor_Diffuse;
801         int loc_DeferredColor_Specular;
802         int loc_DeferredMod_Diffuse;
803         int loc_DeferredMod_Specular;
804         int loc_DistortScaleRefractReflect;
805         int loc_EyePosition;
806         int loc_FogColor;
807         int loc_FogHeightFade;
808         int loc_FogPlane;
809         int loc_FogPlaneViewDist;
810         int loc_FogRangeRecip;
811         int loc_LightColor;
812         int loc_LightDir;
813         int loc_LightPosition;
814         int loc_OffsetMapping_ScaleSteps;
815         int loc_PixelSize;
816         int loc_ReflectColor;
817         int loc_ReflectFactor;
818         int loc_ReflectOffset;
819         int loc_RefractColor;
820         int loc_Saturation;
821         int loc_ScreenCenterRefractReflect;
822         int loc_ScreenScaleRefractReflect;
823         int loc_ScreenToDepth;
824         int loc_ShadowMap_Parameters;
825         int loc_ShadowMap_TextureScale;
826         int loc_SpecularPower;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845 }
846 r_glsl_permutation_t;
847
848 #define SHADERPERMUTATION_HASHSIZE 256
849
850
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
853 enum
854 {
855         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
861         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
862 };
863 #define SHADERSTATICPARMS_COUNT 7
864
865 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
866 static int shaderstaticparms_count = 0;
867
868 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
869 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
870 qboolean R_CompileShader_CheckStaticParms(void)
871 {
872         static int r_compileshader_staticparms_save[1];
873         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
874         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
875
876         // detect all
877         if (r_glsl_saturation_redcompensate.integer)
878                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
879         if (r_glsl_vertextextureblend_usebothalphas.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
881         if (r_shadow_glossexact.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
883         if (r_glsl_postprocess.integer)
884         {
885                 if (r_glsl_postprocess_uservec1_enable.integer)
886                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
887                 if (r_glsl_postprocess_uservec2_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
889                 if (r_glsl_postprocess_uservec3_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
891                 if (r_glsl_postprocess_uservec4_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
893         }
894         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
895 }
896
897 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
898         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
899                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
900         else \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
902 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
903 {
904         shaderstaticparms_count = 0;
905
906         // emit all
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
914 }
915
916 /// information about each possible shader permutation
917 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
918 /// currently selected permutation
919 r_glsl_permutation_t *r_glsl_permutation;
920 /// storage for permutations linked in the hash table
921 memexpandablearray_t r_glsl_permutationarray;
922
923 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
924 {
925         //unsigned int hashdepth = 0;
926         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
927         r_glsl_permutation_t *p;
928         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
929         {
930                 if (p->mode == mode && p->permutation == permutation)
931                 {
932                         //if (hashdepth > 10)
933                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
934                         return p;
935                 }
936                 //hashdepth++;
937         }
938         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
939         p->mode = mode;
940         p->permutation = permutation;
941         p->hashnext = r_glsl_permutationhash[mode][hashindex];
942         r_glsl_permutationhash[mode][hashindex] = p;
943         //if (hashdepth > 10)
944         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945         return p;
946 }
947
948 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
949 {
950         char *shaderstring;
951         if (!filename || !filename[0])
952                 return NULL;
953         if (!strcmp(filename, "glsl/default.glsl"))
954         {
955                 if (!glslshaderstring)
956                 {
957                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
958                         if (glslshaderstring)
959                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
960                         else
961                                 glslshaderstring = (char *)builtinshaderstring;
962                 }
963                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
964                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
965                 return shaderstring;
966         }
967         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968         if (shaderstring)
969         {
970                 if (printfromdisknotice)
971                         Con_DPrintf("from disk %s... ", filename);
972                 return shaderstring;
973         }
974         return shaderstring;
975 }
976
977 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
978 {
979         int i;
980         int sampler;
981         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
982         char *vertexstring, *geometrystring, *fragmentstring;
983         char permutationname[256];
984         int vertstrings_count = 0;
985         int geomstrings_count = 0;
986         int fragstrings_count = 0;
987         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
988         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990
991         if (p->compiled)
992                 return;
993         p->compiled = true;
994         p->program = 0;
995
996         permutationname[0] = 0;
997         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
998         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
999         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1000
1001         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1002
1003         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1004         if(vid.support.gl20shaders130)
1005         {
1006                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1007                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1008                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1009                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1010                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1011                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1012         }
1013
1014         // the first pretext is which type of shader to compile as
1015         // (later these will all be bound together as a program object)
1016         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1017         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1018         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1019
1020         // the second pretext is the mode (for example a light source)
1021         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1022         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1023         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1024         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1025
1026         // now add all the permutation pretexts
1027         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1028         {
1029                 if (permutation & (1<<i))
1030                 {
1031                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1032                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1035                 }
1036                 else
1037                 {
1038                         // keep line numbers correct
1039                         vertstrings_list[vertstrings_count++] = "\n";
1040                         geomstrings_list[geomstrings_count++] = "\n";
1041                         fragstrings_list[fragstrings_count++] = "\n";
1042                 }
1043         }
1044
1045         // add static parms
1046         R_CompileShader_AddStaticParms(mode, permutation);
1047         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048         vertstrings_count += shaderstaticparms_count;
1049         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         geomstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         fragstrings_count += shaderstaticparms_count;
1053
1054         // now append the shader text itself
1055         vertstrings_list[vertstrings_count++] = vertexstring;
1056         geomstrings_list[geomstrings_count++] = geometrystring;
1057         fragstrings_list[fragstrings_count++] = fragmentstring;
1058
1059         // if any sources were NULL, clear the respective list
1060         if (!vertexstring)
1061                 vertstrings_count = 0;
1062         if (!geometrystring)
1063                 geomstrings_count = 0;
1064         if (!fragmentstring)
1065                 fragstrings_count = 0;
1066
1067         // compile the shader program
1068         if (vertstrings_count + geomstrings_count + fragstrings_count)
1069                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1070         if (p->program)
1071         {
1072                 CHECKGLERROR
1073                 qglUseProgram(p->program);CHECKGLERROR
1074                 // look up all the uniform variable names we care about, so we don't
1075                 // have to look them up every time we set them
1076
1077                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1078                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1079                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1080                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1081                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1082                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1083                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1084                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1085                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1086                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1087                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1088                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1089                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1090                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1091                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1092                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1093                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1094                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1095                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1096                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1097                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1098                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1099                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1100                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1101                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1102                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1103                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1104                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1105                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1106                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1107                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1108                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1109                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1110                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1111                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1112                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1113                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1114                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1115                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1116                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1117                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1118                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1119                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1120                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1121                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1122                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1123                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1124                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1125                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1126                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1127                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1128                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1129                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1130                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1131                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1132                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1133                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1134                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1135                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1136                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1137                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1138                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1139                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1140                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1141                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1142                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1143                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1144                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1145                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1146                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1147                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1148                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1149                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1150                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1151                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1152                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1153                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1154                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1155                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1156                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1157                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1158                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1159                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1160                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1161                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1162                 // initialize the samplers to refer to the texture units we use
1163                 p->tex_Texture_First = -1;
1164                 p->tex_Texture_Second = -1;
1165                 p->tex_Texture_GammaRamps = -1;
1166                 p->tex_Texture_Normal = -1;
1167                 p->tex_Texture_Color = -1;
1168                 p->tex_Texture_Gloss = -1;
1169                 p->tex_Texture_Glow = -1;
1170                 p->tex_Texture_SecondaryNormal = -1;
1171                 p->tex_Texture_SecondaryColor = -1;
1172                 p->tex_Texture_SecondaryGloss = -1;
1173                 p->tex_Texture_SecondaryGlow = -1;
1174                 p->tex_Texture_Pants = -1;
1175                 p->tex_Texture_Shirt = -1;
1176                 p->tex_Texture_FogHeightTexture = -1;
1177                 p->tex_Texture_FogMask = -1;
1178                 p->tex_Texture_Lightmap = -1;
1179                 p->tex_Texture_Deluxemap = -1;
1180                 p->tex_Texture_Attenuation = -1;
1181                 p->tex_Texture_Cube = -1;
1182                 p->tex_Texture_Refraction = -1;
1183                 p->tex_Texture_Reflection = -1;
1184                 p->tex_Texture_ShadowMap2D = -1;
1185                 p->tex_Texture_CubeProjection = -1;
1186                 p->tex_Texture_ScreenDepth = -1;
1187                 p->tex_Texture_ScreenNormalMap = -1;
1188                 p->tex_Texture_ScreenDiffuse = -1;
1189                 p->tex_Texture_ScreenSpecular = -1;
1190                 p->tex_Texture_ReflectMask = -1;
1191                 p->tex_Texture_ReflectCube = -1;
1192                 p->tex_Texture_BounceGrid = -1;
1193                 sampler = 0;
1194                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1195                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1196                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1197                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1198                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1199                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1200                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1201                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1205                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1206                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1207                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1208                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1209                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1210                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1211                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1212                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1213                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1214                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1215                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1216                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1217                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1221                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1223                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1224                 CHECKGLERROR
1225                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1226         }
1227         else
1228                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1229
1230         // free the strings
1231         if (vertexstring)
1232                 Mem_Free(vertexstring);
1233         if (geometrystring)
1234                 Mem_Free(geometrystring);
1235         if (fragmentstring)
1236                 Mem_Free(fragmentstring);
1237 }
1238
1239 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1240 {
1241         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1242         if (r_glsl_permutation != perm)
1243         {
1244                 r_glsl_permutation = perm;
1245                 if (!r_glsl_permutation->program)
1246                 {
1247                         if (!r_glsl_permutation->compiled)
1248                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1249                         if (!r_glsl_permutation->program)
1250                         {
1251                                 // remove features until we find a valid permutation
1252                                 int i;
1253                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1254                                 {
1255                                         // reduce i more quickly whenever it would not remove any bits
1256                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1257                                         if (!(permutation & j))
1258                                                 continue;
1259                                         permutation -= j;
1260                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1261                                         if (!r_glsl_permutation->compiled)
1262                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1263                                         if (r_glsl_permutation->program)
1264                                                 break;
1265                                 }
1266                                 if (i >= SHADERPERMUTATION_COUNT)
1267                                 {
1268                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1269                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1270                                         qglUseProgram(0);CHECKGLERROR
1271                                         return; // no bit left to clear, entire mode is broken
1272                                 }
1273                         }
1274                 }
1275                 CHECKGLERROR
1276                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1277         }
1278         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1279         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1280         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1281 }
1282
1283 #ifdef SUPPORTD3D
1284
1285 #ifdef SUPPORTD3D
1286 #include <d3d9.h>
1287 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1288 extern D3DCAPS9 vid_d3d9caps;
1289 #endif
1290
1291 struct r_hlsl_permutation_s;
1292 typedef struct r_hlsl_permutation_s
1293 {
1294         /// hash lookup data
1295         struct r_hlsl_permutation_s *hashnext;
1296         unsigned int mode;
1297         unsigned int permutation;
1298
1299         /// indicates if we have tried compiling this permutation already
1300         qboolean compiled;
1301         /// NULL if compilation failed
1302         IDirect3DVertexShader9 *vertexshader;
1303         IDirect3DPixelShader9 *pixelshader;
1304 }
1305 r_hlsl_permutation_t;
1306
1307 typedef enum D3DVSREGISTER_e
1308 {
1309         D3DVSREGISTER_TexMatrix = 0, // float4x4
1310         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1311         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1312         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1313         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1314         D3DVSREGISTER_ModelToLight = 20, // float4x4
1315         D3DVSREGISTER_EyePosition = 24,
1316         D3DVSREGISTER_FogPlane = 25,
1317         D3DVSREGISTER_LightDir = 26,
1318         D3DVSREGISTER_LightPosition = 27,
1319 }
1320 D3DVSREGISTER_t;
1321
1322 typedef enum D3DPSREGISTER_e
1323 {
1324         D3DPSREGISTER_Alpha = 0,
1325         D3DPSREGISTER_BloomBlur_Parameters = 1,
1326         D3DPSREGISTER_ClientTime = 2,
1327         D3DPSREGISTER_Color_Ambient = 3,
1328         D3DPSREGISTER_Color_Diffuse = 4,
1329         D3DPSREGISTER_Color_Specular = 5,
1330         D3DPSREGISTER_Color_Glow = 6,
1331         D3DPSREGISTER_Color_Pants = 7,
1332         D3DPSREGISTER_Color_Shirt = 8,
1333         D3DPSREGISTER_DeferredColor_Ambient = 9,
1334         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1335         D3DPSREGISTER_DeferredColor_Specular = 11,
1336         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1337         D3DPSREGISTER_DeferredMod_Specular = 13,
1338         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1339         D3DPSREGISTER_EyePosition = 15, // unused
1340         D3DPSREGISTER_FogColor = 16,
1341         D3DPSREGISTER_FogHeightFade = 17,
1342         D3DPSREGISTER_FogPlane = 18,
1343         D3DPSREGISTER_FogPlaneViewDist = 19,
1344         D3DPSREGISTER_FogRangeRecip = 20,
1345         D3DPSREGISTER_LightColor = 21,
1346         D3DPSREGISTER_LightDir = 22, // unused
1347         D3DPSREGISTER_LightPosition = 23,
1348         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1349         D3DPSREGISTER_PixelSize = 25,
1350         D3DPSREGISTER_ReflectColor = 26,
1351         D3DPSREGISTER_ReflectFactor = 27,
1352         D3DPSREGISTER_ReflectOffset = 28,
1353         D3DPSREGISTER_RefractColor = 29,
1354         D3DPSREGISTER_Saturation = 30,
1355         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1356         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1357         D3DPSREGISTER_ScreenToDepth = 33,
1358         D3DPSREGISTER_ShadowMap_Parameters = 34,
1359         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1360         D3DPSREGISTER_SpecularPower = 36,
1361         D3DPSREGISTER_UserVec1 = 37,
1362         D3DPSREGISTER_UserVec2 = 38,
1363         D3DPSREGISTER_UserVec3 = 39,
1364         D3DPSREGISTER_UserVec4 = 40,
1365         D3DPSREGISTER_ViewTintColor = 41,
1366         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1367         D3DPSREGISTER_BloomColorSubtract = 43,
1368         D3DPSREGISTER_ViewToLight = 44, // float4x4
1369         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1370         D3DPSREGISTER_NormalmapScrollBlend = 52,
1371         // next at 53
1372 }
1373 D3DPSREGISTER_t;
1374
1375 /// information about each possible shader permutation
1376 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1377 /// currently selected permutation
1378 r_hlsl_permutation_t *r_hlsl_permutation;
1379 /// storage for permutations linked in the hash table
1380 memexpandablearray_t r_hlsl_permutationarray;
1381
1382 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1383 {
1384         //unsigned int hashdepth = 0;
1385         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1386         r_hlsl_permutation_t *p;
1387         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1388         {
1389                 if (p->mode == mode && p->permutation == permutation)
1390                 {
1391                         //if (hashdepth > 10)
1392                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1393                         return p;
1394                 }
1395                 //hashdepth++;
1396         }
1397         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1398         p->mode = mode;
1399         p->permutation = permutation;
1400         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1401         r_hlsl_permutationhash[mode][hashindex] = p;
1402         //if (hashdepth > 10)
1403         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404         return p;
1405 }
1406
1407 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1408 {
1409         char *shaderstring;
1410         if (!filename || !filename[0])
1411                 return NULL;
1412         if (!strcmp(filename, "hlsl/default.hlsl"))
1413         {
1414                 if (!hlslshaderstring)
1415                 {
1416                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1417                         if (hlslshaderstring)
1418                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1419                         else
1420                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1421                 }
1422                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1423                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1424                 return shaderstring;
1425         }
1426         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427         if (shaderstring)
1428         {
1429                 if (printfromdisknotice)
1430                         Con_DPrintf("from disk %s... ", filename);
1431                 return shaderstring;
1432         }
1433         return shaderstring;
1434 }
1435
1436 #include <d3dx9.h>
1437 //#include <d3dx9shader.h>
1438 //#include <d3dx9mesh.h>
1439
1440 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1441 {
1442         DWORD *vsbin = NULL;
1443         DWORD *psbin = NULL;
1444         fs_offset_t vsbinsize;
1445         fs_offset_t psbinsize;
1446 //      IDirect3DVertexShader9 *vs = NULL;
1447 //      IDirect3DPixelShader9 *ps = NULL;
1448         ID3DXBuffer *vslog = NULL;
1449         ID3DXBuffer *vsbuffer = NULL;
1450         ID3DXConstantTable *vsconstanttable = NULL;
1451         ID3DXBuffer *pslog = NULL;
1452         ID3DXBuffer *psbuffer = NULL;
1453         ID3DXConstantTable *psconstanttable = NULL;
1454         int vsresult = 0;
1455         int psresult = 0;
1456         char temp[MAX_INPUTLINE];
1457         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1458         qboolean debugshader = gl_paranoid.integer != 0;
1459         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (!debugshader)
1462         {
1463                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1464                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1465         }
1466         if ((!vsbin && vertstring) || (!psbin && fragstring))
1467         {
1468                 const char* dllnames_d3dx9 [] =
1469                 {
1470                         "d3dx9_43.dll",
1471                         "d3dx9_42.dll",
1472                         "d3dx9_41.dll",
1473                         "d3dx9_40.dll",
1474                         "d3dx9_39.dll",
1475                         "d3dx9_38.dll",
1476                         "d3dx9_37.dll",
1477                         "d3dx9_36.dll",
1478                         "d3dx9_35.dll",
1479                         "d3dx9_34.dll",
1480                         "d3dx9_33.dll",
1481                         "d3dx9_32.dll",
1482                         "d3dx9_31.dll",
1483                         "d3dx9_30.dll",
1484                         "d3dx9_29.dll",
1485                         "d3dx9_28.dll",
1486                         "d3dx9_27.dll",
1487                         "d3dx9_26.dll",
1488                         "d3dx9_25.dll",
1489                         "d3dx9_24.dll",
1490                         NULL
1491                 };
1492                 dllhandle_t d3dx9_dll = NULL;
1493                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1495                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 dllfunction_t d3dx9_dllfuncs[] =
1497                 {
1498                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1499                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1500                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1501                         {NULL, NULL}
1502                 };
1503                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1504                 {
1505                         DWORD shaderflags = 0;
1506                         if (debugshader)
1507                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1508                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1509                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1510                         if (vertstring && vertstring[0])
1511                         {
1512                                 if (debugshader)
1513                                 {
1514 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1515 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1516                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1517                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1518                                 }
1519                                 else
1520                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1521                                 if (vsbuffer)
1522                                 {
1523                                         vsbinsize = vsbuffer->GetBufferSize();
1524                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1525                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1526                                         vsbuffer->Release();
1527                                 }
1528                                 if (vslog)
1529                                 {
1530                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1531                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1532                                         vslog->Release();
1533                                 }
1534                         }
1535                         if (fragstring && fragstring[0])
1536                         {
1537                                 if (debugshader)
1538                                 {
1539 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1540 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1541                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1542                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1543                                 }
1544                                 else
1545                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1546                                 if (psbuffer)
1547                                 {
1548                                         psbinsize = psbuffer->GetBufferSize();
1549                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1550                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1551                                         psbuffer->Release();
1552                                 }
1553                                 if (pslog)
1554                                 {
1555                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1556                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1557                                         pslog->Release();
1558                                 }
1559                         }
1560                         Sys_UnloadLibrary(&d3dx9_dll);
1561                 }
1562                 else
1563                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1564         }
1565         if (vsbin && psbin)
1566         {
1567                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1568                 if (FAILED(vsresult))
1569                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1570                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1571                 if (FAILED(psresult))
1572                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1573         }
1574         // free the shader data
1575         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1576         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1577 }
1578
1579 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1580 {
1581         int i;
1582         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1583         int vertstring_length = 0;
1584         int geomstring_length = 0;
1585         int fragstring_length = 0;
1586         char *t;
1587         char *vertexstring, *geometrystring, *fragmentstring;
1588         char *vertstring, *geomstring, *fragstring;
1589         char permutationname[256];
1590         char cachename[256];
1591         int vertstrings_count = 0;
1592         int geomstrings_count = 0;
1593         int fragstrings_count = 0;
1594         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597
1598         if (p->compiled)
1599                 return;
1600         p->compiled = true;
1601         p->vertexshader = NULL;
1602         p->pixelshader = NULL;
1603
1604         permutationname[0] = 0;
1605         cachename[0] = 0;
1606         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1607         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1608         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1609
1610         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1611         strlcat(cachename, "hlsl/", sizeof(cachename));
1612
1613         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1614         vertstrings_count = 0;
1615         geomstrings_count = 0;
1616         fragstrings_count = 0;
1617         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1618         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1619         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1620
1621         // the first pretext is which type of shader to compile as
1622         // (later these will all be bound together as a program object)
1623         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1624         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1625         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1626
1627         // the second pretext is the mode (for example a light source)
1628         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1629         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1630         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1631         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1632         strlcat(cachename, modeinfo->name, sizeof(cachename));
1633
1634         // now add all the permutation pretexts
1635         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1636         {
1637                 if (permutation & (1<<i))
1638                 {
1639                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1643                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1644                 }
1645                 else
1646                 {
1647                         // keep line numbers correct
1648                         vertstrings_list[vertstrings_count++] = "\n";
1649                         geomstrings_list[geomstrings_count++] = "\n";
1650                         fragstrings_list[fragstrings_count++] = "\n";
1651                 }
1652         }
1653
1654         // add static parms
1655         R_CompileShader_AddStaticParms(mode, permutation);
1656         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         vertstrings_count += shaderstaticparms_count;
1658         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         geomstrings_count += shaderstaticparms_count;
1660         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         fragstrings_count += shaderstaticparms_count;
1662
1663         // replace spaces in the cachename with _ characters
1664         for (i = 0;cachename[i];i++)
1665                 if (cachename[i] == ' ')
1666                         cachename[i] = '_';
1667
1668         // now append the shader text itself
1669         vertstrings_list[vertstrings_count++] = vertexstring;
1670         geomstrings_list[geomstrings_count++] = geometrystring;
1671         fragstrings_list[fragstrings_count++] = fragmentstring;
1672
1673         // if any sources were NULL, clear the respective list
1674         if (!vertexstring)
1675                 vertstrings_count = 0;
1676         if (!geometrystring)
1677                 geomstrings_count = 0;
1678         if (!fragmentstring)
1679                 fragstrings_count = 0;
1680
1681         vertstring_length = 0;
1682         for (i = 0;i < vertstrings_count;i++)
1683                 vertstring_length += strlen(vertstrings_list[i]);
1684         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1685         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1686                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1687
1688         geomstring_length = 0;
1689         for (i = 0;i < geomstrings_count;i++)
1690                 geomstring_length += strlen(geomstrings_list[i]);
1691         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1692         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1693                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1694
1695         fragstring_length = 0;
1696         for (i = 0;i < fragstrings_count;i++)
1697                 fragstring_length += strlen(fragstrings_list[i]);
1698         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1699         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1700                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1701
1702         // try to load the cached shader, or generate one
1703         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1704
1705         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1706                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1707         else
1708                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1709
1710         // free the strings
1711         if (vertstring)
1712                 Mem_Free(vertstring);
1713         if (geomstring)
1714                 Mem_Free(geomstring);
1715         if (fragstring)
1716                 Mem_Free(fragstring);
1717         if (vertexstring)
1718                 Mem_Free(vertexstring);
1719         if (geometrystring)
1720                 Mem_Free(geometrystring);
1721         if (fragmentstring)
1722                 Mem_Free(fragmentstring);
1723 }
1724
1725 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1726 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1727 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1728 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1731
1732 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738
1739 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1740 {
1741         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1742         if (r_hlsl_permutation != perm)
1743         {
1744                 r_hlsl_permutation = perm;
1745                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                 {
1747                         if (!r_hlsl_permutation->compiled)
1748                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1749                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1750                         {
1751                                 // remove features until we find a valid permutation
1752                                 int i;
1753                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1754                                 {
1755                                         // reduce i more quickly whenever it would not remove any bits
1756                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1757                                         if (!(permutation & j))
1758                                                 continue;
1759                                         permutation -= j;
1760                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1761                                         if (!r_hlsl_permutation->compiled)
1762                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1763                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1764                                                 break;
1765                                 }
1766                                 if (i >= SHADERPERMUTATION_COUNT)
1767                                 {
1768                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1769                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1770                                         return; // no bit left to clear, entire mode is broken
1771                                 }
1772                         }
1773                 }
1774                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1775                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1776         }
1777         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1779         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1780 }
1781 #endif
1782
1783 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1784 {
1785         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1786         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1788         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1789 }
1790
1791 void R_GLSL_Restart_f(void)
1792 {
1793         unsigned int i, limit;
1794         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1795                 Mem_Free(glslshaderstring);
1796         glslshaderstring = NULL;
1797         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1798                 Mem_Free(hlslshaderstring);
1799         hlslshaderstring = NULL;
1800         switch(vid.renderpath)
1801         {
1802         case RENDERPATH_D3D9:
1803 #ifdef SUPPORTD3D
1804                 {
1805                         r_hlsl_permutation_t *p;
1806                         r_hlsl_permutation = NULL;
1807                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1808                         for (i = 0;i < limit;i++)
1809                         {
1810                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1811                                 {
1812                                         if (p->vertexshader)
1813                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1814                                         if (p->pixelshader)
1815                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1816                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1817                                 }
1818                         }
1819                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1820                 }
1821 #endif
1822                 break;
1823         case RENDERPATH_D3D10:
1824                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1825                 break;
1826         case RENDERPATH_D3D11:
1827                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1828                 break;
1829         case RENDERPATH_GL20:
1830         case RENDERPATH_GLES2:
1831                 {
1832                         r_glsl_permutation_t *p;
1833                         r_glsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1838                                 {
1839                                         GL_Backend_FreeProgram(p->program);
1840                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1844                 }
1845                 break;
1846         case RENDERPATH_GL11:
1847         case RENDERPATH_GL13:
1848         case RENDERPATH_GLES1:
1849                 break;
1850         case RENDERPATH_SOFT:
1851                 break;
1852         }
1853 }
1854
1855 void R_GLSL_DumpShader_f(void)
1856 {
1857         int i;
1858         qfile_t *file;
1859
1860         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1861         if (file)
1862         {
1863                 FS_Print(file, "/* The engine may define the following macros:\n");
1864                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1865                 for (i = 0;i < SHADERMODE_COUNT;i++)
1866                         FS_Print(file, glslshadermodeinfo[i].pretext);
1867                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1868                         FS_Print(file, shaderpermutationinfo[i].pretext);
1869                 FS_Print(file, "*/\n");
1870                 FS_Print(file, builtinshaderstring);
1871                 FS_Close(file);
1872                 Con_Printf("glsl/default.glsl written\n");
1873         }
1874         else
1875                 Con_Printf("failed to write to glsl/default.glsl\n");
1876
1877         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1878         if (file)
1879         {
1880                 FS_Print(file, "/* The engine may define the following macros:\n");
1881                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1882                 for (i = 0;i < SHADERMODE_COUNT;i++)
1883                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1884                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885                         FS_Print(file, shaderpermutationinfo[i].pretext);
1886                 FS_Print(file, "*/\n");
1887                 FS_Print(file, builtinhlslshaderstring);
1888                 FS_Close(file);
1889                 Con_Printf("hlsl/default.hlsl written\n");
1890         }
1891         else
1892                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1893 }
1894
1895 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1896 {
1897         if (!second)
1898                 texturemode = GL_MODULATE;
1899         switch (vid.renderpath)
1900         {
1901         case RENDERPATH_D3D9:
1902 #ifdef SUPPORTD3D
1903                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1904                 R_Mesh_TexBind(GL20TU_FIRST , first );
1905                 R_Mesh_TexBind(GL20TU_SECOND, second);
1906 #endif
1907                 break;
1908         case RENDERPATH_D3D10:
1909                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910                 break;
1911         case RENDERPATH_D3D11:
1912                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1913                 break;
1914         case RENDERPATH_GL20:
1915         case RENDERPATH_GLES2:
1916                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1917                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1918                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1919                 break;
1920         case RENDERPATH_GL13:
1921         case RENDERPATH_GLES1:
1922                 R_Mesh_TexBind(0, first );
1923                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1924                 R_Mesh_TexBind(1, second);
1925                 if (second)
1926                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1927                 break;
1928         case RENDERPATH_GL11:
1929                 R_Mesh_TexBind(0, first );
1930                 break;
1931         case RENDERPATH_SOFT:
1932                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1933                 R_Mesh_TexBind(GL20TU_FIRST , first );
1934                 R_Mesh_TexBind(GL20TU_SECOND, second);
1935                 break;
1936         }
1937 }
1938
1939 void R_SetupShader_DepthOrShadow(void)
1940 {
1941         switch (vid.renderpath)
1942         {
1943         case RENDERPATH_D3D9:
1944 #ifdef SUPPORTD3D
1945                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1946 #endif
1947                 break;
1948         case RENDERPATH_D3D10:
1949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950                 break;
1951         case RENDERPATH_D3D11:
1952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_GL20:
1955         case RENDERPATH_GLES2:
1956                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1957                 break;
1958         case RENDERPATH_GL13:
1959         case RENDERPATH_GLES1:
1960                 R_Mesh_TexBind(0, 0);
1961                 R_Mesh_TexBind(1, 0);
1962                 break;
1963         case RENDERPATH_GL11:
1964                 R_Mesh_TexBind(0, 0);
1965                 break;
1966         case RENDERPATH_SOFT:
1967                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1968                 break;
1969         }
1970 }
1971
1972 void R_SetupShader_ShowDepth(void)
1973 {
1974         switch (vid.renderpath)
1975         {
1976         case RENDERPATH_D3D9:
1977 #ifdef SUPPORTHLSL
1978                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1979 #endif
1980                 break;
1981         case RENDERPATH_D3D10:
1982                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_D3D11:
1985                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_GL20:
1988         case RENDERPATH_GLES2:
1989                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1990                 break;
1991         case RENDERPATH_GL13:
1992         case RENDERPATH_GLES1:
1993                 break;
1994         case RENDERPATH_GL11:
1995                 break;
1996         case RENDERPATH_SOFT:
1997                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1998                 break;
1999         }
2000 }
2001
2002 extern qboolean r_shadow_usingdeferredprepass;
2003 extern cvar_t r_shadow_deferred_8bitrange;
2004 extern rtexture_t *r_shadow_attenuationgradienttexture;
2005 extern rtexture_t *r_shadow_attenuation2dtexture;
2006 extern rtexture_t *r_shadow_attenuation3dtexture;
2007 extern qboolean r_shadow_usingshadowmap2d;
2008 extern qboolean r_shadow_usingshadowmaportho;
2009 extern float r_shadow_shadowmap_texturescale[2];
2010 extern float r_shadow_shadowmap_parameters[4];
2011 extern qboolean r_shadow_shadowmapvsdct;
2012 extern qboolean r_shadow_shadowmapsampler;
2013 extern int r_shadow_shadowmappcf;
2014 extern rtexture_t *r_shadow_shadowmap2dtexture;
2015 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2016 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2017 extern matrix4x4_t r_shadow_shadowmapmatrix;
2018 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2019 extern int r_shadow_prepass_width;
2020 extern int r_shadow_prepass_height;
2021 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2022 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2023 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2024 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2025 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2026
2027 #define BLENDFUNC_ALLOWS_COLORMOD      1
2028 #define BLENDFUNC_ALLOWS_FOG           2
2029 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2030 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2031 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2032 static int R_BlendFuncFlags(int src, int dst)
2033 {
2034         int r = 0;
2035
2036         // a blendfunc allows colormod if:
2037         // a) it can never keep the destination pixel invariant, or
2038         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2039         // this is to prevent unintended side effects from colormod
2040
2041         // a blendfunc allows fog if:
2042         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2043         // this is to prevent unintended side effects from fog
2044
2045         // these checks are the output of fogeval.pl
2046
2047         r |= BLENDFUNC_ALLOWS_COLORMOD;
2048         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2049         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2050         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2051         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2052         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2053         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2054         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2057         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2058         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2060         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2061         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2063         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2064         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2067         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069
2070         return r;
2071 }
2072
2073 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2074 {
2075         // select a permutation of the lighting shader appropriate to this
2076         // combination of texture, entity, light source, and fogging, only use the
2077         // minimum features necessary to avoid wasting rendering time in the
2078         // fragment shader on features that are not being used
2079         unsigned int permutation = 0;
2080         unsigned int mode = 0;
2081         int blendfuncflags;
2082         static float dummy_colormod[3] = {1, 1, 1};
2083         float *colormod = rsurface.colormod;
2084         float m16f[16];
2085         matrix4x4_t tempmatrix;
2086         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2087         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2088                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2089         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2090                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2091         if (rsurfacepass == RSURFPASS_BACKGROUND)
2092         {
2093                 // distorted background
2094                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2095                 {
2096                         mode = SHADERMODE_WATER;
2097                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2098                         {
2099                                 // this is the right thing to do for wateralpha
2100                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2101                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2102                         }
2103                         else
2104                         {
2105                                 // this is the right thing to do for entity alpha
2106                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2107                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2108                         }
2109                 }
2110                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2111                 {
2112                         mode = SHADERMODE_REFRACTION;
2113                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2114                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2115                 }
2116                 else
2117                 {
2118                         mode = SHADERMODE_GENERIC;
2119                         permutation |= SHADERPERMUTATION_DIFFUSE;
2120                         GL_BlendFunc(GL_ONE, GL_ZERO);
2121                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2122                 }
2123         }
2124         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2125         {
2126                 if (r_glsl_offsetmapping.integer)
2127                 {
2128                         switch(rsurface.texture->offsetmapping)
2129                         {
2130                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2131                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2132                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2133                         case OFFSETMAPPING_OFF: break;
2134                         }
2135                 }
2136                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2137                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2138                 // normalmap (deferred prepass), may use alpha test on diffuse
2139                 mode = SHADERMODE_DEFERREDGEOMETRY;
2140                 GL_BlendFunc(GL_ONE, GL_ZERO);
2141                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2142         }
2143         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2144         {
2145                 if (r_glsl_offsetmapping.integer)
2146                 {
2147                         switch(rsurface.texture->offsetmapping)
2148                         {
2149                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2150                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2151                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2152                         case OFFSETMAPPING_OFF: break;
2153                         }
2154                 }
2155                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2156                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2157                 // light source
2158                 mode = SHADERMODE_LIGHTSOURCE;
2159                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2160                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2161                 if (diffusescale > 0)
2162                         permutation |= SHADERPERMUTATION_DIFFUSE;
2163                 if (specularscale > 0)
2164                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2165                 if (r_refdef.fogenabled)
2166                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2167                 if (rsurface.texture->colormapping)
2168                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2169                 if (r_shadow_usingshadowmap2d)
2170                 {
2171                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2172                         if(r_shadow_shadowmapvsdct)
2173                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2174
2175                         if (r_shadow_shadowmapsampler)
2176                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2177                         if (r_shadow_shadowmappcf > 1)
2178                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2179                         else if (r_shadow_shadowmappcf)
2180                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2181                 }
2182                 if (rsurface.texture->reflectmasktexture)
2183                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2184                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2185                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2186         }
2187         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer)
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 // unshaded geometry (fullbright or ambient model lighting)
2202                 mode = SHADERMODE_FLATCOLOR;
2203                 ambientscale = diffusescale = specularscale = 0;
2204                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2205                         permutation |= SHADERPERMUTATION_GLOW;
2206                 if (r_refdef.fogenabled)
2207                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2208                 if (rsurface.texture->colormapping)
2209                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2210                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2211                 {
2212                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2213                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2214
2215                         if (r_shadow_shadowmapsampler)
2216                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2217                         if (r_shadow_shadowmappcf > 1)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2219                         else if (r_shadow_shadowmappcf)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2221                 }
2222                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2223                         permutation |= SHADERPERMUTATION_REFLECTION;
2224                 if (rsurface.texture->reflectmasktexture)
2225                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2226                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2227                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2228         }
2229         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2230         {
2231                 if (r_glsl_offsetmapping.integer)
2232                 {
2233                         switch(rsurface.texture->offsetmapping)
2234                         {
2235                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238                         case OFFSETMAPPING_OFF: break;
2239                         }
2240                 }
2241                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243                 // directional model lighting
2244                 mode = SHADERMODE_LIGHTDIRECTION;
2245                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2246                         permutation |= SHADERPERMUTATION_GLOW;
2247                 permutation |= SHADERPERMUTATION_DIFFUSE;
2248                 if (specularscale > 0)
2249                         permutation |= SHADERPERMUTATION_SPECULAR;
2250                 if (r_refdef.fogenabled)
2251                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2252                 if (rsurface.texture->colormapping)
2253                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2254                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2255                 {
2256                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2257                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2258
2259                         if (r_shadow_shadowmapsampler)
2260                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2261                         if (r_shadow_shadowmappcf > 1)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2263                         else if (r_shadow_shadowmappcf)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2267                         permutation |= SHADERPERMUTATION_REFLECTION;
2268                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2269                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 if (r_shadow_bouncegridtexture)
2273                 {
2274                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2275                         if (r_shadow_bouncegriddirectional)
2276                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2277                 }
2278                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280         }
2281         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2282         {
2283                 if (r_glsl_offsetmapping.integer)
2284                 {
2285                         switch(rsurface.texture->offsetmapping)
2286                         {
2287                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_OFF: break;
2291                         }
2292                 }
2293                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295                 // ambient model lighting
2296                 mode = SHADERMODE_LIGHTDIRECTION;
2297                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2298                         permutation |= SHADERPERMUTATION_GLOW;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329         }
2330         else
2331         {
2332                 if (r_glsl_offsetmapping.integer)
2333                 {
2334                         switch(rsurface.texture->offsetmapping)
2335                         {
2336                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2337                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2338                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2339                         case OFFSETMAPPING_OFF: break;
2340                         }
2341                 }
2342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2343                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2344                 // lightmapped wall
2345                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346                         permutation |= SHADERPERMUTATION_GLOW;
2347                 if (r_refdef.fogenabled)
2348                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349                 if (rsurface.texture->colormapping)
2350                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2351                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352                 {
2353                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355
2356                         if (r_shadow_shadowmapsampler)
2357                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2358                         if (r_shadow_shadowmappcf > 1)
2359                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2360                         else if (r_shadow_shadowmappcf)
2361                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2362                 }
2363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2364                         permutation |= SHADERPERMUTATION_REFLECTION;
2365                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2366                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2367                 if (rsurface.texture->reflectmasktexture)
2368                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2369                 if (FAKELIGHT_ENABLED)
2370                 {
2371                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2372                         mode = SHADERMODE_FAKELIGHT;
2373                         permutation |= SHADERPERMUTATION_DIFFUSE;
2374                         if (specularscale > 0)
2375                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2376                 }
2377                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2378                 {
2379                         // deluxemapping (light direction texture)
2380                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2381                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2382                         else
2383                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2384                         permutation |= SHADERPERMUTATION_DIFFUSE;
2385                         if (specularscale > 0)
2386                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2387                 }
2388                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2389                 {
2390                         // fake deluxemapping (uniform light direction in tangentspace)
2391                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2392                         permutation |= SHADERPERMUTATION_DIFFUSE;
2393                         if (specularscale > 0)
2394                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2395                 }
2396                 else if (rsurface.uselightmaptexture)
2397                 {
2398                         // ordinary lightmapping (q1bsp, q3bsp)
2399                         mode = SHADERMODE_LIGHTMAP;
2400                 }
2401                 else
2402                 {
2403                         // ordinary vertex coloring (q3bsp)
2404                         mode = SHADERMODE_VERTEXCOLOR;
2405                 }
2406                 if (r_shadow_bouncegridtexture)
2407                 {
2408                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2409                         if (r_shadow_bouncegriddirectional)
2410                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2411                 }
2412                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414         }
2415         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2416                 colormod = dummy_colormod;
2417         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2418                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2419         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2420                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2421         switch(vid.renderpath)
2422         {
2423         case RENDERPATH_D3D9:
2424 #ifdef SUPPORTD3D
2425                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2426                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2427                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2428                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2429                 if (mode == SHADERMODE_LIGHTSOURCE)
2430                 {
2431                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2432                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2433                 }
2434                 else
2435                 {
2436                         if (mode == SHADERMODE_LIGHTDIRECTION)
2437                         {
2438                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2439                         }
2440                 }
2441                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2442                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2443                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2444                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2445                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2446
2447                 if (mode == SHADERMODE_LIGHTSOURCE)
2448                 {
2449                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2450                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2451                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2452                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2453                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2454
2455                         // additive passes are only darkened by fog, not tinted
2456                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2457                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2458                 }
2459                 else
2460                 {
2461                         if (mode == SHADERMODE_FLATCOLOR)
2462                         {
2463                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2464                         }
2465                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2466                         {
2467                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2468                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2469                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2471                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2472                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2473                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2474                         }
2475                         else
2476                         {
2477                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2481                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2482                         }
2483                         // additive passes are only darkened by fog, not tinted
2484                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2486                         else
2487                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2488                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2489                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2490                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2491                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2492                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2493                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2494                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2495                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2496                         if (mode == SHADERMODE_WATER)
2497                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2498                 }
2499                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2500                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2501                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2502                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2503                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2504                 if (rsurface.texture->pantstexture)
2505                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2506                 else
2507                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2508                 if (rsurface.texture->shirttexture)
2509                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2510                 else
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2512                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2513                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2514                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2515                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2516                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2517                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2518                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2519                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2520                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2521                         );
2522                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2523                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2524
2525                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2526                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2527                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2528                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2529                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2530                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2531                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2532                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2533                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2534                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2535                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2536                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2537                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2538                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2539                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2540                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2541                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2542                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2543                 {
2544                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2545                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2546                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2547                 }
2548                 else
2549                 {
2550                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2551                 }
2552 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2553 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2554                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2555                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2556                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2557                 {
2558                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2559                         if (rsurface.rtlight)
2560                         {
2561                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2562                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2563                         }
2564                 }
2565 #endif
2566                 break;
2567         case RENDERPATH_D3D10:
2568                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2569                 break;
2570         case RENDERPATH_D3D11:
2571                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2572                 break;
2573         case RENDERPATH_GL20:
2574         case RENDERPATH_GLES2:
2575                 if (!vid.useinterleavedarrays)
2576                 {
2577                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2578                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2579                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2580                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2581                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2582                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2583                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2584                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2585                 }
2586                 else
2587                 {
2588                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2589                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2590                 }
2591                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2592                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2593                 if (mode == SHADERMODE_LIGHTSOURCE)
2594                 {
2595                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2596                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2597                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2598                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2599                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2600                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2601         
2602                         // additive passes are only darkened by fog, not tinted
2603                         if (r_glsl_permutation->loc_FogColor >= 0)
2604                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2605                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606                 }
2607                 else
2608                 {
2609                         if (mode == SHADERMODE_FLATCOLOR)
2610                         {
2611                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2612                         }
2613                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2614                         {
2615                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2616                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2617                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2618                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2619                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2620                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2621                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2622                         }
2623                         else
2624                         {
2625                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2626                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2627                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2628                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2629                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2630                         }
2631                         // additive passes are only darkened by fog, not tinted
2632                         if (r_glsl_permutation->loc_FogColor >= 0)
2633                         {
2634                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2635                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2636                                 else
2637                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2638                         }
2639                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2640                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2641                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2642                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2643                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2644                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2645                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2646                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2647                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2648                 }
2649                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2650                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2651                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2652                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2653                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2654
2655                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2656                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2657                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2658                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2659                 {
2660                         if (rsurface.texture->pantstexture)
2661                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2662                         else
2663                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2664                 }
2665                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2666                 {
2667                         if (rsurface.texture->shirttexture)
2668                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2669                         else
2670                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2671                 }
2672                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2673                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2674                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2675                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2676                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2677                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2678                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2679                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2680                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2681                         );
2682                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2683                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2684                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2685                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2686
2687                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2688                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2689                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2690                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2691                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2692                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2693                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2694                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2695                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2696                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2697                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2698                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2699                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2700                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2701                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2702                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2703                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2704                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2705                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2706                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2707                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2708                 {
2709                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2710                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2711                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2712                 }
2713                 else
2714                 {
2715                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2716                 }
2717                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2718                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2719                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2720                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2721                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2722                 {
2723                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2724                         if (rsurface.rtlight)
2725                         {
2726                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2727                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2728                         }
2729                 }
2730                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2731                 CHECKGLERROR
2732                 break;
2733         case RENDERPATH_GL11:
2734         case RENDERPATH_GL13:
2735         case RENDERPATH_GLES1:
2736                 break;
2737         case RENDERPATH_SOFT:
2738                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2739                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2740                 R_SetupShader_SetPermutationSoft(mode, permutation);
2741                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2742                 if (mode == SHADERMODE_LIGHTSOURCE)
2743                 {
2744                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2745                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2746                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2747                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2748                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2749                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2750         
2751                         // additive passes are only darkened by fog, not tinted
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2753                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2754                 }
2755                 else
2756                 {
2757                         if (mode == SHADERMODE_FLATCOLOR)
2758                         {
2759                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2760                         }
2761                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2762                         {
2763                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2764                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2765                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2767                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2768                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2769                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2770                         }
2771                         else
2772                         {
2773                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2775                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2777                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2778                         }
2779                         // additive passes are only darkened by fog, not tinted
2780                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2782                         else
2783                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2784                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2785                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2786                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2787                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2788                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2789                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2790                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2791                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2792                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2793                 }
2794                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2795                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2796                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2797                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2798                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2799
2800                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2801                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2802                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2803                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2804                 {
2805                         if (rsurface.texture->pantstexture)
2806                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2807                         else
2808                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2809                 }
2810                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2811                 {
2812                         if (rsurface.texture->shirttexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2816                 }
2817                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2818                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2819                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2820                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2821                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2822                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2823                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2824                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2825                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2826                         );
2827                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2828                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2829
2830                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2831                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2832                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2833                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2834                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2835                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2836                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2837                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2838                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2839                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2840                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2841                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2842                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2843                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2844                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2845                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2846                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2847                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2848                 {
2849                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2850                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2851                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2852                 }
2853                 else
2854                 {
2855                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2856                 }
2857 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2858 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2859                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2860                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2861                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2862                 {
2863                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2864                         if (rsurface.rtlight)
2865                         {
2866                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2867                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2868                         }
2869                 }
2870                 break;
2871         }
2872 }
2873
2874 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2875 {
2876         // select a permutation of the lighting shader appropriate to this
2877         // combination of texture, entity, light source, and fogging, only use the
2878         // minimum features necessary to avoid wasting rendering time in the
2879         // fragment shader on features that are not being used
2880         unsigned int permutation = 0;
2881         unsigned int mode = 0;
2882         const float *lightcolorbase = rtlight->currentcolor;
2883         float ambientscale = rtlight->ambientscale;
2884         float diffusescale = rtlight->diffusescale;
2885         float specularscale = rtlight->specularscale;
2886         // this is the location of the light in view space
2887         vec3_t viewlightorigin;
2888         // this transforms from view space (camera) to light space (cubemap)
2889         matrix4x4_t viewtolight;
2890         matrix4x4_t lighttoview;
2891         float viewtolight16f[16];
2892         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2893         // light source
2894         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2895         if (rtlight->currentcubemap != r_texture_whitecube)
2896                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2897         if (diffusescale > 0)
2898                 permutation |= SHADERPERMUTATION_DIFFUSE;
2899         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2900                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2901         if (r_shadow_usingshadowmap2d)
2902         {
2903                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2904                 if (r_shadow_shadowmapvsdct)
2905                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2906
2907                 if (r_shadow_shadowmapsampler)
2908                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2909                 if (r_shadow_shadowmappcf > 1)
2910                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2911                 else if (r_shadow_shadowmappcf)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2913         }
2914         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2915         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2916         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2917         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2918         switch(vid.renderpath)
2919         {
2920         case RENDERPATH_D3D9:
2921 #ifdef SUPPORTD3D
2922                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2923                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2924                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2925                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2926                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2927                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2928                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2929                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2930                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2931                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2932                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2933
2934                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2935                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2936                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2937                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2938                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2939                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2940 #endif
2941                 break;
2942         case RENDERPATH_D3D10:
2943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2944                 break;
2945         case RENDERPATH_D3D11:
2946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2947                 break;
2948         case RENDERPATH_GL20:
2949         case RENDERPATH_GLES2:
2950                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2951                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2952                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2953                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2954                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2955                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2956                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2957                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2958                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2959                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2960                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2961
2962                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2963                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2964                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2965                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2966                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2967                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2968                 break;
2969         case RENDERPATH_GL11:
2970         case RENDERPATH_GL13:
2971         case RENDERPATH_GLES1:
2972                 break;
2973         case RENDERPATH_SOFT:
2974                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2975                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2976                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2977                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2978                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2979                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2980                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2981                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2982                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2983                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2984                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2985
2986                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2987                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2988                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2989                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2990                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2991                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2992                 break;
2993         }
2994 }
2995
2996 #define SKINFRAME_HASH 1024
2997
2998 typedef struct
2999 {
3000         int loadsequence; // incremented each level change
3001         memexpandablearray_t array;
3002         skinframe_t *hash[SKINFRAME_HASH];
3003 }
3004 r_skinframe_t;
3005 r_skinframe_t r_skinframe;
3006
3007 void R_SkinFrame_PrepareForPurge(void)
3008 {
3009         r_skinframe.loadsequence++;
3010         // wrap it without hitting zero
3011         if (r_skinframe.loadsequence >= 200)
3012                 r_skinframe.loadsequence = 1;
3013 }
3014
3015 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3016 {
3017         if (!skinframe)
3018                 return;
3019         // mark the skinframe as used for the purging code
3020         skinframe->loadsequence = r_skinframe.loadsequence;
3021 }
3022
3023 void R_SkinFrame_Purge(void)
3024 {
3025         int i;
3026         skinframe_t *s;
3027         for (i = 0;i < SKINFRAME_HASH;i++)
3028         {
3029                 for (s = r_skinframe.hash[i];s;s = s->next)
3030                 {
3031                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3032                         {
3033                                 if (s->merged == s->base)
3034                                         s->merged = NULL;
3035                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3036                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3037                                 R_PurgeTexture(s->merged);s->merged = NULL;
3038                                 R_PurgeTexture(s->base  );s->base   = NULL;
3039                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3040                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3041                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3042                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3043                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3044                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3045                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3046                                 s->loadsequence = 0;
3047                         }
3048                 }
3049         }
3050 }
3051
3052 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3053         skinframe_t *item;
3054         char basename[MAX_QPATH];
3055
3056         Image_StripImageExtension(name, basename, sizeof(basename));
3057
3058         if( last == NULL ) {
3059                 int hashindex;
3060                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3061                 item = r_skinframe.hash[hashindex];
3062         } else {
3063                 item = last->next;
3064         }
3065
3066         // linearly search through the hash bucket
3067         for( ; item ; item = item->next ) {
3068                 if( !strcmp( item->basename, basename ) ) {
3069                         return item;
3070                 }
3071         }
3072         return NULL;
3073 }
3074
3075 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3076 {
3077         skinframe_t *item;
3078         int hashindex;
3079         char basename[MAX_QPATH];
3080
3081         Image_StripImageExtension(name, basename, sizeof(basename));
3082
3083         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3084         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3085                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3086                         break;
3087
3088         if (!item) {
3089                 rtexture_t *dyntexture;
3090                 // check whether its a dynamic texture
3091                 dyntexture = CL_GetDynTexture( basename );
3092                 if (!add && !dyntexture)
3093                         return NULL;
3094                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3095                 memset(item, 0, sizeof(*item));
3096                 strlcpy(item->basename, basename, sizeof(item->basename));
3097                 item->base = dyntexture; // either NULL or dyntexture handle
3098                 item->textureflags = textureflags;
3099                 item->comparewidth = comparewidth;
3100                 item->compareheight = compareheight;
3101                 item->comparecrc = comparecrc;
3102                 item->next = r_skinframe.hash[hashindex];
3103                 r_skinframe.hash[hashindex] = item;
3104         }
3105         else if( item->base == NULL )
3106         {
3107                 rtexture_t *dyntexture;
3108                 // check whether its a dynamic texture
3109                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3110                 dyntexture = CL_GetDynTexture( basename );
3111                 item->base = dyntexture; // either NULL or dyntexture handle
3112         }
3113
3114         R_SkinFrame_MarkUsed(item);
3115         return item;
3116 }
3117
3118 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3119         { \
3120                 unsigned long long avgcolor[5], wsum; \
3121                 int pix, comp, w; \
3122                 avgcolor[0] = 0; \
3123                 avgcolor[1] = 0; \
3124                 avgcolor[2] = 0; \
3125                 avgcolor[3] = 0; \
3126                 avgcolor[4] = 0; \
3127                 wsum = 0; \
3128                 for(pix = 0; pix < cnt; ++pix) \
3129                 { \
3130                         w = 0; \
3131                         for(comp = 0; comp < 3; ++comp) \
3132                                 w += getpixel; \
3133                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3134                         { \
3135                                 ++wsum; \
3136                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3137                                 w = getpixel; \
3138                                 for(comp = 0; comp < 3; ++comp) \
3139                                         avgcolor[comp] += getpixel * w; \
3140                                 avgcolor[3] += w; \
3141                         } \
3142                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3143                         avgcolor[4] += getpixel; \
3144                 } \
3145                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3146                         avgcolor[3] = 1; \
3147                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3148                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3149                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3150                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3151         }
3152
3153 extern cvar_t gl_picmip;
3154 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3155 {
3156         int j;
3157         unsigned char *pixels;
3158         unsigned char *bumppixels;
3159         unsigned char *basepixels = NULL;
3160         int basepixels_width = 0;
3161         int basepixels_height = 0;
3162         skinframe_t *skinframe;
3163         rtexture_t *ddsbase = NULL;
3164         qboolean ddshasalpha = false;
3165         float ddsavgcolor[4];
3166         char basename[MAX_QPATH];
3167         int miplevel = R_PicmipForFlags(textureflags);
3168         int savemiplevel = miplevel;
3169         int mymiplevel;
3170
3171         if (cls.state == ca_dedicated)
3172                 return NULL;
3173
3174         // return an existing skinframe if already loaded
3175         // if loading of the first image fails, don't make a new skinframe as it
3176         // would cause all future lookups of this to be missing
3177         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3178         if (skinframe && skinframe->base)
3179                 return skinframe;
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         // check for DDS texture file first
3184         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3185         {
3186                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3187                 if (basepixels == NULL)
3188                         return NULL;
3189         }
3190
3191         // FIXME handle miplevel
3192
3193         if (developer_loading.integer)
3194                 Con_Printf("loading skin \"%s\"\n", name);
3195
3196         // we've got some pixels to store, so really allocate this new texture now
3197         if (!skinframe)
3198                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3199         skinframe->stain = NULL;
3200         skinframe->merged = NULL;
3201         skinframe->base = NULL;
3202         skinframe->pants = NULL;
3203         skinframe->shirt = NULL;
3204         skinframe->nmap = NULL;
3205         skinframe->gloss = NULL;
3206         skinframe->glow = NULL;
3207         skinframe->fog = NULL;
3208         skinframe->reflect = NULL;
3209         skinframe->hasalpha = false;
3210
3211         if (ddsbase)
3212         {
3213                 skinframe->base = ddsbase;
3214                 skinframe->hasalpha = ddshasalpha;
3215                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3216                 if (r_loadfog && skinframe->hasalpha)
3217                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3218                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3219         }
3220         else
3221         {
3222                 basepixels_width = image_width;
3223                 basepixels_height = image_height;
3224                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3225                 if (textureflags & TEXF_ALPHA)
3226                 {
3227                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3228                         {
3229                                 if (basepixels[j] < 255)
3230                                 {
3231                                         skinframe->hasalpha = true;
3232                                         break;
3233                                 }
3234                         }
3235                         if (r_loadfog && skinframe->hasalpha)
3236                         {
3237                                 // has transparent pixels
3238                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3239                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3240                                 {
3241                                         pixels[j+0] = 255;
3242                                         pixels[j+1] = 255;
3243                                         pixels[j+2] = 255;
3244                                         pixels[j+3] = basepixels[j+3];
3245                                 }
3246                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3247                                 Mem_Free(pixels);
3248                         }
3249                 }
3250                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3251                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3252                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3253                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3254                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3255                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3256         }
3257
3258         if (r_loaddds)
3259         {
3260                 mymiplevel = savemiplevel;
3261                 if (r_loadnormalmap)
3262                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3263                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3264                 if (r_loadgloss)
3265                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3266                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3267                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3268                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269         }
3270
3271         // _norm is the name used by tenebrae and has been adopted as standard
3272         if (r_loadnormalmap && skinframe->nmap == NULL)
3273         {
3274                 mymiplevel = savemiplevel;
3275                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3276                 {
3277                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3278                         Mem_Free(pixels);
3279                         pixels = NULL;
3280                 }
3281                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3282                 {
3283                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3284                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3285                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3286                         Mem_Free(pixels);
3287                         Mem_Free(bumppixels);
3288                 }
3289                 else if (r_shadow_bumpscale_basetexture.value > 0)
3290                 {
3291                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3292                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3293                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3294                         Mem_Free(pixels);
3295                 }
3296                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3297                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3298         }
3299
3300         // _luma is supported only for tenebrae compatibility
3301         // _glow is the preferred name
3302         mymiplevel = savemiplevel;
3303         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3304         {
3305                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3306                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3307                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3308                 Mem_Free(pixels);pixels = NULL;
3309         }
3310
3311         mymiplevel = savemiplevel;
3312         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3313         {
3314                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3315                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3316                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3317                 Mem_Free(pixels);
3318                 pixels = NULL;
3319         }
3320
3321         mymiplevel = savemiplevel;
3322         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3323         {
3324                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3325                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3326                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3327                 Mem_Free(pixels);
3328                 pixels = NULL;
3329         }
3330
3331         mymiplevel = savemiplevel;
3332         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3333         {
3334                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3336                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3337                 Mem_Free(pixels);
3338                 pixels = NULL;
3339         }
3340
3341         mymiplevel = savemiplevel;
3342         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3343         {
3344                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3345                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3346                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3347                 Mem_Free(pixels);
3348                 pixels = NULL;
3349         }
3350
3351         if (basepixels)
3352                 Mem_Free(basepixels);
3353
3354         return skinframe;
3355 }
3356
3357 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3358 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3359 {
3360         int i;
3361         unsigned char *temp1, *temp2;
3362         skinframe_t *skinframe;
3363
3364         if (cls.state == ca_dedicated)
3365                 return NULL;
3366
3367         // if already loaded just return it, otherwise make a new skinframe
3368         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3369         if (skinframe && skinframe->base)
3370                 return skinframe;
3371
3372         skinframe->stain = NULL;
3373         skinframe->merged = NULL;
3374         skinframe->base = NULL;
3375         skinframe->pants = NULL;
3376         skinframe->shirt = NULL;
3377         skinframe->nmap = NULL;
3378         skinframe->gloss = NULL;
3379         skinframe->glow = NULL;
3380         skinframe->fog = NULL;
3381         skinframe->reflect = NULL;
3382         skinframe->hasalpha = false;
3383
3384         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3385         if (!skindata)
3386                 return NULL;
3387
3388         if (developer_loading.integer)
3389                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3390
3391         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3392         {
3393                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3394                 temp2 = temp1 + width * height * 4;
3395                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3396                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3397                 Mem_Free(temp1);
3398         }
3399         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3400         if (textureflags & TEXF_ALPHA)
3401         {
3402                 for (i = 3;i < width * height * 4;i += 4)
3403                 {
3404                         if (skindata[i] < 255)
3405                         {
3406                                 skinframe->hasalpha = true;
3407                                 break;
3408                         }
3409                 }
3410                 if (r_loadfog && skinframe->hasalpha)
3411                 {
3412                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3413                         memcpy(fogpixels, skindata, width * height * 4);
3414                         for (i = 0;i < width * height * 4;i += 4)
3415                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3416                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3417                         Mem_Free(fogpixels);
3418                 }
3419         }
3420
3421         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3422         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3423
3424         return skinframe;
3425 }
3426
3427 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3428 {
3429         int i;
3430         int featuresmask;
3431         skinframe_t *skinframe;
3432
3433         if (cls.state == ca_dedicated)
3434                 return NULL;
3435
3436         // if already loaded just return it, otherwise make a new skinframe
3437         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3438         if (skinframe && skinframe->base)
3439                 return skinframe;
3440
3441         skinframe->stain = NULL;
3442         skinframe->merged = NULL;
3443         skinframe->base = NULL;
3444         skinframe->pants = NULL;
3445         skinframe->shirt = NULL;
3446         skinframe->nmap = NULL;
3447         skinframe->gloss = NULL;
3448         skinframe->glow = NULL;
3449         skinframe->fog = NULL;
3450         skinframe->reflect = NULL;
3451         skinframe->hasalpha = false;
3452
3453         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3454         if (!skindata)
3455                 return NULL;
3456
3457         if (developer_loading.integer)
3458                 Con_Printf("loading quake skin \"%s\"\n", name);
3459
3460         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3461         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3462         memcpy(skinframe->qpixels, skindata, width*height);
3463         skinframe->qwidth = width;
3464         skinframe->qheight = height;
3465
3466         featuresmask = 0;
3467         for (i = 0;i < width * height;i++)
3468                 featuresmask |= palette_featureflags[skindata[i]];
3469
3470         skinframe->hasalpha = false;
3471         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3472         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3473         skinframe->qgeneratemerged = true;
3474         skinframe->qgeneratebase = skinframe->qhascolormapping;
3475         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3476
3477         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3478         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3479
3480         return skinframe;
3481 }
3482
3483 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3484 {
3485         int width;
3486         int height;
3487         unsigned char *skindata;
3488
3489         if (!skinframe->qpixels)
3490                 return;
3491
3492         if (!skinframe->qhascolormapping)
3493                 colormapped = false;
3494
3495         if (colormapped)
3496         {
3497                 if (!skinframe->qgeneratebase)
3498                         return;
3499         }
3500         else
3501         {
3502                 if (!skinframe->qgeneratemerged)
3503                         return;
3504         }
3505
3506         width = skinframe->qwidth;
3507         height = skinframe->qheight;
3508         skindata = skinframe->qpixels;
3509
3510         if (skinframe->qgeneratenmap)
3511         {
3512                 unsigned char *temp1, *temp2;
3513                 skinframe->qgeneratenmap = false;
3514                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3515                 temp2 = temp1 + width * height * 4;
3516                 // use either a custom palette or the quake palette
3517                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3518                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3519                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3520                 Mem_Free(temp1);
3521         }
3522
3523         if (skinframe->qgenerateglow)
3524         {
3525                 skinframe->qgenerateglow = false;
3526                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3527         }
3528
3529         if (colormapped)
3530         {
3531                 skinframe->qgeneratebase = false;
3532                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3533                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3534                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3535         }
3536         else
3537         {
3538                 skinframe->qgeneratemerged = false;
3539                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3540         }
3541
3542         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3543         {
3544                 Mem_Free(skinframe->qpixels);
3545                 skinframe->qpixels = NULL;
3546         }
3547 }
3548
3549 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3550 {
3551         int i;
3552         skinframe_t *skinframe;
3553
3554         if (cls.state == ca_dedicated)
3555                 return NULL;
3556
3557         // if already loaded just return it, otherwise make a new skinframe
3558         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3559         if (skinframe && skinframe->base)
3560                 return skinframe;
3561
3562         skinframe->stain = NULL;
3563         skinframe->merged = NULL;
3564         skinframe->base = NULL;
3565         skinframe->pants = NULL;
3566         skinframe->shirt = NULL;
3567         skinframe->nmap = NULL;
3568         skinframe->gloss = NULL;
3569         skinframe->glow = NULL;
3570         skinframe->fog = NULL;
3571         skinframe->reflect = NULL;
3572         skinframe->hasalpha = false;
3573
3574         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3575         if (!skindata)
3576                 return NULL;
3577
3578         if (developer_loading.integer)
3579                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3580
3581         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3582         if (textureflags & TEXF_ALPHA)
3583         {
3584                 for (i = 0;i < width * height;i++)
3585                 {
3586                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3587                         {
3588                                 skinframe->hasalpha = true;
3589                                 break;
3590                         }
3591                 }
3592                 if (r_loadfog && skinframe->hasalpha)
3593                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3594         }
3595
3596         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3597         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3598
3599         return skinframe;
3600 }
3601
3602 skinframe_t *R_SkinFrame_LoadMissing(void)
3603 {
3604         skinframe_t *skinframe;
3605
3606         if (cls.state == ca_dedicated)
3607                 return NULL;
3608
3609         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3610         skinframe->stain = NULL;
3611         skinframe->merged = NULL;
3612         skinframe->base = NULL;
3613         skinframe->pants = NULL;
3614         skinframe->shirt = NULL;
3615         skinframe->nmap = NULL;
3616         skinframe->gloss = NULL;
3617         skinframe->glow = NULL;
3618         skinframe->fog = NULL;
3619         skinframe->reflect = NULL;
3620         skinframe->hasalpha = false;
3621
3622         skinframe->avgcolor[0] = rand() / RAND_MAX;
3623         skinframe->avgcolor[1] = rand() / RAND_MAX;
3624         skinframe->avgcolor[2] = rand() / RAND_MAX;
3625         skinframe->avgcolor[3] = 1;
3626
3627         return skinframe;
3628 }
3629
3630 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3631 typedef struct suffixinfo_s
3632 {
3633         const char *suffix;
3634         qboolean flipx, flipy, flipdiagonal;
3635 }
3636 suffixinfo_t;
3637 static suffixinfo_t suffix[3][6] =
3638 {
3639         {
3640                 {"px",   false, false, false},
3641                 {"nx",   false, false, false},
3642                 {"py",   false, false, false},
3643                 {"ny",   false, false, false},
3644                 {"pz",   false, false, false},
3645                 {"nz",   false, false, false}
3646         },
3647         {
3648                 {"posx", false, false, false},
3649                 {"negx", false, false, false},
3650                 {"posy", false, false, false},
3651                 {"negy", false, false, false},
3652                 {"posz", false, false, false},
3653                 {"negz", false, false, false}
3654         },
3655         {
3656                 {"rt",    true, false,  true},
3657                 {"lf",   false,  true,  true},
3658                 {"ft",    true,  true, false},
3659                 {"bk",   false, false, false},
3660                 {"up",    true, false,  true},
3661                 {"dn",    true, false,  true}
3662         }
3663 };
3664
3665 static int componentorder[4] = {0, 1, 2, 3};
3666
3667 rtexture_t *R_LoadCubemap(const char *basename)
3668 {
3669         int i, j, cubemapsize;
3670         unsigned char *cubemappixels, *image_buffer;
3671         rtexture_t *cubemaptexture;
3672         char name[256];
3673         // must start 0 so the first loadimagepixels has no requested width/height
3674         cubemapsize = 0;
3675         cubemappixels = NULL;
3676         cubemaptexture = NULL;
3677         // keep trying different suffix groups (posx, px, rt) until one loads
3678         for (j = 0;j < 3 && !cubemappixels;j++)
3679         {
3680                 // load the 6 images in the suffix group
3681                 for (i = 0;i < 6;i++)
3682                 {
3683                         // generate an image name based on the base and and suffix
3684                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3685                         // load it
3686                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3687                         {
3688                                 // an image loaded, make sure width and height are equal
3689                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3690                                 {
3691                                         // if this is the first image to load successfully, allocate the cubemap memory
3692                                         if (!cubemappixels && image_width >= 1)
3693                                         {
3694                                                 cubemapsize = image_width;
3695                                                 // note this clears to black, so unavailable sides are black
3696                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3697                                         }
3698                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3699                                         if (cubemappixels)
3700                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3701                                 }
3702                                 else
3703                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3704                                 // free the image
3705                                 Mem_Free(image_buffer);
3706                         }
3707                 }
3708         }
3709         // if a cubemap loaded, upload it
3710         if (cubemappixels)
3711         {
3712                 if (developer_loading.integer)
3713                         Con_Printf("loading cubemap \"%s\"\n", basename);
3714
3715                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3716                 Mem_Free(cubemappixels);
3717         }
3718         else
3719         {
3720                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3721                 if (developer_loading.integer)
3722                 {
3723                         Con_Printf("(tried tried images ");
3724                         for (j = 0;j < 3;j++)
3725                                 for (i = 0;i < 6;i++)
3726                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3727                         Con_Print(" and was unable to find any of them).\n");
3728                 }
3729         }
3730         return cubemaptexture;
3731 }
3732
3733 rtexture_t *R_GetCubemap(const char *basename)
3734 {
3735         int i;
3736         for (i = 0;i < r_texture_numcubemaps;i++)
3737                 if (r_texture_cubemaps[i] != NULL)
3738                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3739                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3740         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3741                 return r_texture_whitecube;
3742         r_texture_numcubemaps++;
3743         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3744         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3745         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3746         return r_texture_cubemaps[i]->texture;
3747 }
3748
3749 void R_FreeCubemap(const char *basename)
3750 {
3751         int i;
3752
3753         for (i = 0;i < r_texture_numcubemaps;i++)
3754         {
3755                 if (r_texture_cubemaps[i] != NULL)
3756                 {
3757                         if (r_texture_cubemaps[i]->texture)
3758                         {
3759                                 if (developer_loading.integer)
3760                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3761                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3762                                 Mem_Free(r_texture_cubemaps[i]);
3763                                 r_texture_cubemaps[i] = NULL;
3764                         }
3765                 }
3766         }
3767 }
3768
3769 void R_FreeCubemaps(void)
3770 {
3771         int i;
3772         for (i = 0;i < r_texture_numcubemaps;i++)
3773         {
3774                 if (developer_loading.integer)
3775                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3776                 if (r_texture_cubemaps[i] != NULL)
3777                 {
3778                         if (r_texture_cubemaps[i]->texture)
3779                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3780                         Mem_Free(r_texture_cubemaps[i]);
3781                 }
3782         }
3783         r_texture_numcubemaps = 0;
3784 }
3785
3786 void R_Main_FreeViewCache(void)
3787 {
3788         if (r_refdef.viewcache.entityvisible)
3789                 Mem_Free(r_refdef.viewcache.entityvisible);
3790         if (r_refdef.viewcache.world_pvsbits)
3791                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3792         if (r_refdef.viewcache.world_leafvisible)
3793                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3794         if (r_refdef.viewcache.world_surfacevisible)
3795                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3796         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3797 }
3798
3799 void R_Main_ResizeViewCache(void)
3800 {
3801         int numentities = r_refdef.scene.numentities;
3802         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3803         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3804         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3805         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3806         if (r_refdef.viewcache.maxentities < numentities)
3807         {
3808                 r_refdef.viewcache.maxentities = numentities;
3809                 if (r_refdef.viewcache.entityvisible)
3810                         Mem_Free(r_refdef.viewcache.entityvisible);
3811                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3812         }
3813         if (r_refdef.viewcache.world_numclusters != numclusters)
3814         {
3815                 r_refdef.viewcache.world_numclusters = numclusters;
3816                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3817                 if (r_refdef.viewcache.world_pvsbits)
3818                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3819                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3820         }
3821         if (r_refdef.viewcache.world_numleafs != numleafs)
3822         {
3823                 r_refdef.viewcache.world_numleafs = numleafs;
3824                 if (r_refdef.viewcache.world_leafvisible)
3825                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3826                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3827         }
3828         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3829         {
3830                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3831                 if (r_refdef.viewcache.world_surfacevisible)
3832                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3833                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3834         }
3835 }
3836
3837 extern rtexture_t *loadingscreentexture;
3838 void gl_main_start(void)
3839 {
3840         loadingscreentexture = NULL;
3841         r_texture_blanknormalmap = NULL;
3842         r_texture_white = NULL;
3843         r_texture_grey128 = NULL;
3844         r_texture_black = NULL;
3845         r_texture_whitecube = NULL;
3846         r_texture_normalizationcube = NULL;
3847         r_texture_fogattenuation = NULL;
3848         r_texture_fogheighttexture = NULL;
3849         r_texture_gammaramps = NULL;
3850         r_texture_numcubemaps = 0;
3851
3852         r_loaddds = r_texture_dds_load.integer != 0;
3853         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3854
3855         switch(vid.renderpath)
3856         {
3857         case RENDERPATH_GL20:
3858         case RENDERPATH_D3D9:
3859         case RENDERPATH_D3D10:
3860         case RENDERPATH_D3D11:
3861         case RENDERPATH_SOFT:
3862         case RENDERPATH_GLES2:
3863                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3864                 Cvar_SetValueQuick(&gl_combine, 1);
3865                 Cvar_SetValueQuick(&r_glsl, 1);
3866                 r_loadnormalmap = true;
3867                 r_loadgloss = true;
3868                 r_loadfog = false;
3869                 break;
3870         case RENDERPATH_GL13:
3871         case RENDERPATH_GLES1:
3872                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3873                 Cvar_SetValueQuick(&gl_combine, 1);
3874                 Cvar_SetValueQuick(&r_glsl, 0);
3875                 r_loadnormalmap = false;
3876                 r_loadgloss = false;
3877                 r_loadfog = true;
3878                 break;
3879         case RENDERPATH_GL11:
3880                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3881                 Cvar_SetValueQuick(&gl_combine, 0);
3882                 Cvar_SetValueQuick(&r_glsl, 0);
3883                 r_loadnormalmap = false;
3884                 r_loadgloss = false;
3885                 r_loadfog = true;
3886                 break;
3887         }
3888
3889         R_AnimCache_Free();
3890         R_FrameData_Reset();
3891
3892         r_numqueries = 0;
3893         r_maxqueries = 0;
3894         memset(r_queries, 0, sizeof(r_queries));
3895
3896         r_qwskincache = NULL;
3897         r_qwskincache_size = 0;
3898
3899         // due to caching of texture_t references, the collision cache must be reset
3900         Collision_Cache_Reset(true);
3901
3902         // set up r_skinframe loading system for textures
3903         memset(&r_skinframe, 0, sizeof(r_skinframe));
3904         r_skinframe.loadsequence = 1;
3905         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3906
3907         r_main_texturepool = R_AllocTexturePool();
3908         R_BuildBlankTextures();
3909         R_BuildNoTexture();
3910         if (vid.support.arb_texture_cube_map)
3911         {
3912                 R_BuildWhiteCube();
3913                 R_BuildNormalizationCube();
3914         }
3915         r_texture_fogattenuation = NULL;
3916         r_texture_fogheighttexture = NULL;
3917         r_texture_gammaramps = NULL;
3918         //r_texture_fogintensity = NULL;
3919         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3920         memset(&r_waterstate, 0, sizeof(r_waterstate));
3921         r_glsl_permutation = NULL;
3922         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3923         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3924         glslshaderstring = NULL;
3925 #ifdef SUPPORTD3D
3926         r_hlsl_permutation = NULL;
3927         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3928         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3929 #endif
3930         hlslshaderstring = NULL;
3931         memset(&r_svbsp, 0, sizeof (r_svbsp));
3932
3933         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
3934         r_texture_numcubemaps = 0;
3935
3936         r_refdef.fogmasktable_density = 0;
3937 }
3938
3939 void gl_main_shutdown(void)
3940 {
3941         R_AnimCache_Free();
3942         R_FrameData_Reset();
3943
3944         R_Main_FreeViewCache();
3945
3946         switch(vid.renderpath)
3947         {
3948         case RENDERPATH_GL11:
3949         case RENDERPATH_GL13:
3950         case RENDERPATH_GL20:
3951         case RENDERPATH_GLES1:
3952         case RENDERPATH_GLES2:
3953                 if (r_maxqueries)
3954                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3955                 break;
3956         case RENDERPATH_D3D9:
3957                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3958                 break;
3959         case RENDERPATH_D3D10:
3960                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3961                 break;
3962         case RENDERPATH_D3D11:
3963                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3964                 break;
3965         case RENDERPATH_SOFT:
3966                 break;
3967         }
3968
3969         r_numqueries = 0;
3970         r_maxqueries = 0;
3971         memset(r_queries, 0, sizeof(r_queries));
3972
3973         r_qwskincache = NULL;
3974         r_qwskincache_size = 0;
3975
3976         // clear out the r_skinframe state
3977         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3978         memset(&r_skinframe, 0, sizeof(r_skinframe));
3979
3980         if (r_svbsp.nodes)
3981                 Mem_Free(r_svbsp.nodes);
3982         memset(&r_svbsp, 0, sizeof (r_svbsp));
3983         R_FreeTexturePool(&r_main_texturepool);
3984         loadingscreentexture = NULL;
3985         r_texture_blanknormalmap = NULL;
3986         r_texture_white = NULL;
3987         r_texture_grey128 = NULL;
3988         r_texture_black = NULL;
3989         r_texture_whitecube = NULL;
3990         r_texture_normalizationcube = NULL;
3991         r_texture_fogattenuation = NULL;
3992         r_texture_fogheighttexture = NULL;
3993         r_texture_gammaramps = NULL;
3994         r_texture_numcubemaps = 0;
3995         //r_texture_fogintensity = NULL;
3996         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3997         memset(&r_waterstate, 0, sizeof(r_waterstate));
3998         R_GLSL_Restart_f();
3999
4000         r_glsl_permutation = NULL;
4001         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4002         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4003         glslshaderstring = NULL;
4004 #ifdef SUPPORTD3D
4005         r_hlsl_permutation = NULL;
4006         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4007         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4008 #endif
4009         hlslshaderstring = NULL;
4010 }
4011
4012 extern void CL_ParseEntityLump(char *entitystring);
4013 void gl_main_newmap(void)
4014 {
4015         // FIXME: move this code to client
4016         char *entities, entname[MAX_QPATH];
4017         if (r_qwskincache)
4018                 Mem_Free(r_qwskincache);
4019         r_qwskincache = NULL;
4020         r_qwskincache_size = 0;
4021         if (cl.worldmodel)
4022         {
4023                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4024                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4025                 {
4026                         CL_ParseEntityLump(entities);
4027                         Mem_Free(entities);
4028                         return;
4029                 }
4030                 if (cl.worldmodel->brush.entities)
4031                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4032         }
4033         R_Main_FreeViewCache();
4034
4035         R_FrameData_Reset();
4036 }
4037
4038 void GL_Main_Init(void)
4039 {
4040         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4041
4042         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4043         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4044         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4045         if (gamemode == GAME_NEHAHRA)
4046         {
4047                 Cvar_RegisterVariable (&gl_fogenable);
4048                 Cvar_RegisterVariable (&gl_fogdensity);
4049                 Cvar_RegisterVariable (&gl_fogred);
4050                 Cvar_RegisterVariable (&gl_foggreen);
4051                 Cvar_RegisterVariable (&gl_fogblue);
4052                 Cvar_RegisterVariable (&gl_fogstart);
4053                 Cvar_RegisterVariable (&gl_fogend);
4054                 Cvar_RegisterVariable (&gl_skyclip);
4055         }
4056         Cvar_RegisterVariable(&r_motionblur);
4057         Cvar_RegisterVariable(&r_motionblur_maxblur);
4058         Cvar_RegisterVariable(&r_motionblur_bmin);
4059         Cvar_RegisterVariable(&r_motionblur_vmin);
4060         Cvar_RegisterVariable(&r_motionblur_vmax);
4061         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4062         Cvar_RegisterVariable(&r_motionblur_randomize);
4063         Cvar_RegisterVariable(&r_damageblur);
4064         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4065         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4066         Cvar_RegisterVariable(&r_equalize_entities_by);
4067         Cvar_RegisterVariable(&r_equalize_entities_to);
4068         Cvar_RegisterVariable(&r_depthfirst);
4069         Cvar_RegisterVariable(&r_useinfinitefarclip);
4070         Cvar_RegisterVariable(&r_farclip_base);
4071         Cvar_RegisterVariable(&r_farclip_world);
4072         Cvar_RegisterVariable(&r_nearclip);
4073         Cvar_RegisterVariable(&r_deformvertexes);
4074         Cvar_RegisterVariable(&r_transparent);
4075         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4076         Cvar_RegisterVariable(&r_showoverdraw);
4077         Cvar_RegisterVariable(&r_showbboxes);
4078         Cvar_RegisterVariable(&r_showsurfaces);
4079         Cvar_RegisterVariable(&r_showtris);
4080         Cvar_RegisterVariable(&r_shownormals);
4081         Cvar_RegisterVariable(&r_showlighting);
4082         Cvar_RegisterVariable(&r_showshadowvolumes);
4083         Cvar_RegisterVariable(&r_showcollisionbrushes);
4084         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4085         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4086         Cvar_RegisterVariable(&r_showdisabledepthtest);
4087         Cvar_RegisterVariable(&r_drawportals);
4088         Cvar_RegisterVariable(&r_drawentities);
4089         Cvar_RegisterVariable(&r_draw2d);
4090         Cvar_RegisterVariable(&r_drawworld);
4091         Cvar_RegisterVariable(&r_cullentities_trace);
4092         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4093         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4094         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4095         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4096         Cvar_RegisterVariable(&r_drawviewmodel);
4097         Cvar_RegisterVariable(&r_drawexteriormodel);
4098         Cvar_RegisterVariable(&r_speeds);
4099         Cvar_RegisterVariable(&r_fullbrights);
4100         Cvar_RegisterVariable(&r_wateralpha);
4101         Cvar_RegisterVariable(&r_dynamic);
4102         Cvar_RegisterVariable(&r_fakelight);
4103         Cvar_RegisterVariable(&r_fakelight_intensity);
4104         Cvar_RegisterVariable(&r_fullbright);
4105         Cvar_RegisterVariable(&r_shadows);
4106         Cvar_RegisterVariable(&r_shadows_darken);
4107         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4108         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4109         Cvar_RegisterVariable(&r_shadows_throwdistance);
4110         Cvar_RegisterVariable(&r_shadows_throwdirection);
4111         Cvar_RegisterVariable(&r_shadows_focus);
4112         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4113         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4114         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4115         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4116         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4117         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4118         Cvar_RegisterVariable(&r_fog_exp2);
4119         Cvar_RegisterVariable(&r_fog_clear);
4120         Cvar_RegisterVariable(&r_drawfog);
4121         Cvar_RegisterVariable(&r_transparentdepthmasking);
4122         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4123         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4124         Cvar_RegisterVariable(&r_texture_dds_load);
4125         Cvar_RegisterVariable(&r_texture_dds_save);
4126         Cvar_RegisterVariable(&r_textureunits);
4127         Cvar_RegisterVariable(&gl_combine);
4128         Cvar_RegisterVariable(&r_viewfbo);
4129         Cvar_RegisterVariable(&r_viewscale);
4130         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4131         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4132         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4133         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4134         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4135         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4136         Cvar_RegisterVariable(&r_glsl);
4137         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4138         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4139         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4140         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4141         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4142         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4143         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4144         Cvar_RegisterVariable(&r_glsl_postprocess);
4145         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4146         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4147         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4148         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4149         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4150         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4151         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4152         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4153
4154         Cvar_RegisterVariable(&r_water);
4155         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4156         Cvar_RegisterVariable(&r_water_clippingplanebias);
4157         Cvar_RegisterVariable(&r_water_refractdistort);
4158         Cvar_RegisterVariable(&r_water_reflectdistort);
4159         Cvar_RegisterVariable(&r_water_scissormode);
4160         Cvar_RegisterVariable(&r_water_lowquality);
4161
4162         Cvar_RegisterVariable(&r_lerpsprites);
4163         Cvar_RegisterVariable(&r_lerpmodels);
4164         Cvar_RegisterVariable(&r_lerplightstyles);
4165         Cvar_RegisterVariable(&r_waterscroll);
4166         Cvar_RegisterVariable(&r_bloom);
4167         Cvar_RegisterVariable(&r_bloom_colorscale);
4168         Cvar_RegisterVariable(&r_bloom_brighten);
4169         Cvar_RegisterVariable(&r_bloom_blur);
4170         Cvar_RegisterVariable(&r_bloom_resolution);
4171         Cvar_RegisterVariable(&r_bloom_colorexponent);
4172         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4173         Cvar_RegisterVariable(&r_hdr);
4174         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4175         Cvar_RegisterVariable(&r_hdr_glowintensity);
4176         Cvar_RegisterVariable(&r_hdr_range);
4177         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4178         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4179         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4180         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4181         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4182         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4183         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4184         Cvar_RegisterVariable(&developer_texturelogging);
4185         Cvar_RegisterVariable(&gl_lightmaps);
4186         Cvar_RegisterVariable(&r_test);
4187         Cvar_RegisterVariable(&r_glsl_saturation);
4188         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4189         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4190         Cvar_RegisterVariable(&r_framedatasize);
4191         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4192                 Cvar_SetValue("r_fullbrights", 0);
4193         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4194 }
4195
4196 extern void R_Textures_Init(void);
4197 extern void GL_Draw_Init(void);
4198 extern void GL_Main_Init(void);
4199 extern void R_Shadow_Init(void);
4200 extern void R_Sky_Init(void);
4201 extern void GL_Surf_Init(void);
4202 extern void R_Particles_Init(void);
4203 extern void R_Explosion_Init(void);
4204 extern void gl_backend_init(void);
4205 extern void Sbar_Init(void);
4206 extern void R_LightningBeams_Init(void);
4207 extern void Mod_RenderInit(void);
4208 extern void Font_Init(void);
4209
4210 void Render_Init(void)
4211 {
4212         gl_backend_init();
4213         R_Textures_Init();
4214         GL_Main_Init();
4215         Font_Init();
4216         GL_Draw_Init();
4217         R_Shadow_Init();
4218         R_Sky_Init();
4219         GL_Surf_Init();
4220         Sbar_Init();
4221         R_Particles_Init();
4222         R_Explosion_Init();
4223         R_LightningBeams_Init();
4224         Mod_RenderInit();
4225 }
4226
4227 /*
4228 ===============
4229 GL_Init
4230 ===============
4231 */
4232 extern char *ENGINE_EXTENSIONS;
4233 void GL_Init (void)
4234 {
4235         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4236         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4237         gl_version = (const char *)qglGetString(GL_VERSION);
4238         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4239
4240         if (!gl_extensions)
4241                 gl_extensions = "";
4242         if (!gl_platformextensions)
4243                 gl_platformextensions = "";
4244
4245         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4246         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4247         Con_Printf("GL_VERSION: %s\n", gl_version);
4248         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4249         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4250
4251         VID_CheckExtensions();
4252
4253         // LordHavoc: report supported extensions
4254         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4255
4256         // clear to black (loading plaque will be seen over this)
4257         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4258 }
4259
4260 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4261 {
4262         int i;
4263         mplane_t *p;
4264         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4265         {
4266                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4267                 if (i == 4)
4268                         continue;
4269                 p = r_refdef.view.frustum + i;
4270                 switch(p->signbits)
4271                 {
4272                 default:
4273                 case 0:
4274                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4275                                 return true;
4276                         break;
4277                 case 1:
4278                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4279                                 return true;
4280                         break;
4281                 case 2:
4282                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4283                                 return true;
4284                         break;
4285                 case 3:
4286                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4287                                 return true;
4288                         break;
4289                 case 4:
4290                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4291                                 return true;
4292                         break;
4293                 case 5:
4294                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4295                                 return true;
4296                         break;
4297                 case 6:
4298                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4299                                 return true;
4300                         break;
4301                 case 7:
4302                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4303                                 return true;
4304                         break;
4305                 }
4306         }
4307         return false;
4308 }
4309
4310 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4311 {
4312         int i;
4313         const mplane_t *p;
4314         for (i = 0;i < numplanes;i++)
4315         {
4316                 p = planes + i;
4317                 switch(p->signbits)
4318                 {
4319                 default:
4320                 case 0:
4321                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4322                                 return true;
4323                         break;
4324                 case 1:
4325                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4326                                 return true;
4327                         break;
4328                 case 2:
4329                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4330                                 return true;
4331                         break;
4332                 case 3:
4333                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4334                                 return true;
4335                         break;
4336                 case 4:
4337                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4338                                 return true;
4339                         break;
4340                 case 5:
4341                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4342                                 return true;
4343                         break;
4344                 case 6:
4345                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4346                                 return true;
4347                         break;
4348                 case 7:
4349                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4350                                 return true;
4351                         break;
4352                 }
4353         }
4354         return false;
4355 }
4356
4357 //==================================================================================
4358
4359 // LordHavoc: this stores temporary data used within the same frame
4360
4361 typedef struct r_framedata_mem_s
4362 {
4363         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4364         size_t size; // how much usable space
4365         size_t current; // how much space in use
4366         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4367         size_t wantedsize; // how much space was allocated
4368         unsigned char *data; // start of real data (16byte aligned)
4369 }
4370 r_framedata_mem_t;
4371
4372 static r_framedata_mem_t *r_framedata_mem;
4373
4374 void R_FrameData_Reset(void)
4375 {
4376         while (r_framedata_mem)
4377         {
4378                 r_framedata_mem_t *next = r_framedata_mem->purge;
4379                 Mem_Free(r_framedata_mem);
4380                 r_framedata_mem = next;
4381         }
4382 }
4383
4384 void R_FrameData_Resize(void)
4385 {
4386         size_t wantedsize;
4387         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4388         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4389         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4390         {
4391                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4392                 newmem->wantedsize = wantedsize;
4393                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4394                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4395                 newmem->current = 0;
4396                 newmem->mark = 0;
4397                 newmem->purge = r_framedata_mem;
4398                 r_framedata_mem = newmem;
4399         }
4400 }
4401
4402 void R_FrameData_NewFrame(void)
4403 {
4404         R_FrameData_Resize();
4405         if (!r_framedata_mem)
4406                 return;
4407         // if we ran out of space on the last frame, free the old memory now
4408         while (r_framedata_mem->purge)
4409         {
4410                 // repeatedly remove the second item in the list, leaving only head
4411                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4412                 Mem_Free(r_framedata_mem->purge);
4413                 r_framedata_mem->purge = next;
4414         }
4415         // reset the current mem pointer
4416         r_framedata_mem->current = 0;
4417         r_framedata_mem->mark = 0;
4418 }
4419
4420 void *R_FrameData_Alloc(size_t size)
4421 {
4422         void *data;
4423
4424         // align to 16 byte boundary - the data pointer is already aligned, so we
4425         // only need to ensure the size of every allocation is also aligned
4426         size = (size + 15) & ~15;
4427
4428         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4429         {
4430                 // emergency - we ran out of space, allocate more memory
4431                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4432                 R_FrameData_Resize();
4433         }
4434
4435         data = r_framedata_mem->data + r_framedata_mem->current;
4436         r_framedata_mem->current += size;
4437
4438         // count the usage for stats
4439         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4440         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4441
4442         return (void *)data;
4443 }
4444
4445 void *R_FrameData_Store(size_t size, void *data)
4446 {
4447         void *d = R_FrameData_Alloc(size);
4448         if (d && data)
4449                 memcpy(d, data, size);
4450         return d;
4451 }
4452
4453 void R_FrameData_SetMark(void)
4454 {
4455         if (!r_framedata_mem)
4456                 return;
4457         r_framedata_mem->mark = r_framedata_mem->current;
4458 }
4459
4460 void R_FrameData_ReturnToMark(void)
4461 {
4462         if (!r_framedata_mem)
4463                 return;
4464         r_framedata_mem->current = r_framedata_mem->mark;
4465 }
4466
4467 //==================================================================================
4468
4469 // LordHavoc: animcache originally written by Echon, rewritten since then
4470
4471 /**
4472  * Animation cache prevents re-generating mesh data for an animated model
4473  * multiple times in one frame for lighting, shadowing, reflections, etc.
4474  */
4475
4476 void R_AnimCache_Free(void)
4477 {
4478 }
4479
4480 void R_AnimCache_ClearCache(void)
4481 {
4482         int i;
4483         entity_render_t *ent;
4484
4485         for (i = 0;i < r_refdef.scene.numentities;i++)
4486         {
4487                 ent = r_refdef.scene.entities[i];
4488                 ent->animcache_vertex3f = NULL;
4489                 ent->animcache_normal3f = NULL;
4490                 ent->animcache_svector3f = NULL;
4491                 ent->animcache_tvector3f = NULL;
4492                 ent->animcache_vertexmesh = NULL;
4493                 ent->animcache_vertex3fbuffer = NULL;
4494                 ent->animcache_vertexmeshbuffer = NULL;
4495         }
4496 }
4497
4498 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4499 {
4500         int i;
4501
4502         // check if we need the meshbuffers
4503         if (!vid.useinterleavedarrays)
4504                 return;
4505
4506         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4507                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4508         // TODO: upload vertex3f buffer?
4509         if (ent->animcache_vertexmesh)
4510         {
4511                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4512                 for (i = 0;i < numvertices;i++)
4513                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4514                 if (ent->animcache_svector3f)
4515                         for (i = 0;i < numvertices;i++)
4516                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4517                 if (ent->animcache_tvector3f)
4518                         for (i = 0;i < numvertices;i++)
4519                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4520                 if (ent->animcache_normal3f)
4521                         for (i = 0;i < numvertices;i++)
4522                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4523                 // TODO: upload vertexmeshbuffer?
4524         }
4525 }
4526
4527 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4528 {
4529         dp_model_t *model = ent->model;
4530         int numvertices;
4531         // see if it's already cached this frame
4532         if (ent->animcache_vertex3f)
4533         {
4534                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4535                 if (wantnormals || wanttangents)
4536                 {
4537                         if (ent->animcache_normal3f)
4538                                 wantnormals = false;
4539                         if (ent->animcache_svector3f)
4540                                 wanttangents = false;
4541                         if (wantnormals || wanttangents)
4542                         {
4543                                 numvertices = model->surfmesh.num_vertices;
4544                                 if (wantnormals)
4545                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546                                 if (wanttangents)
4547                                 {
4548                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550                                 }
4551                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4552                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4553                         }
4554                 }
4555         }
4556         else
4557         {
4558                 // see if this ent is worth caching
4559                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4560                         return false;
4561                 // get some memory for this entity and generate mesh data
4562                 numvertices = model->surfmesh.num_vertices;
4563                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4564                 if (wantnormals)
4565                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566                 if (wanttangents)
4567                 {
4568                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4570                 }
4571                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4572                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4573         }
4574         return true;
4575 }
4576
4577 void R_AnimCache_CacheVisibleEntities(void)
4578 {
4579         int i;
4580         qboolean wantnormals = true;
4581         qboolean wanttangents = !r_showsurfaces.integer;
4582
4583         switch(vid.renderpath)
4584         {
4585         case RENDERPATH_GL20:
4586         case RENDERPATH_D3D9:
4587         case RENDERPATH_D3D10:
4588         case RENDERPATH_D3D11:
4589         case RENDERPATH_GLES2:
4590                 break;
4591         case RENDERPATH_GL11:
4592         case RENDERPATH_GL13:
4593         case RENDERPATH_GLES1:
4594                 wanttangents = false;
4595                 break;
4596         case RENDERPATH_SOFT:
4597                 break;
4598         }
4599
4600         if (r_shownormals.integer)
4601                 wanttangents = wantnormals = true;
4602
4603         // TODO: thread this
4604         // NOTE: R_PrepareRTLights() also caches entities
4605
4606         for (i = 0;i < r_refdef.scene.numentities;i++)
4607                 if (r_refdef.viewcache.entityvisible[i])
4608                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4609 }
4610
4611 //==================================================================================
4612
4613 extern cvar_t r_overheadsprites_pushback;
4614
4615 static void R_View_UpdateEntityLighting (void)
4616 {
4617         int i;
4618         entity_render_t *ent;
4619         vec3_t tempdiffusenormal, avg;
4620         vec_t f, fa, fd, fdd;
4621         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4622
4623         for (i = 0;i < r_refdef.scene.numentities;i++)
4624         {
4625                 ent = r_refdef.scene.entities[i];
4626
4627                 // skip unseen models
4628                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4629                         continue;
4630
4631                 // skip bsp models
4632                 if (ent->model && ent->model->brush.num_leafs)
4633                 {
4634                         // TODO: use modellight for r_ambient settings on world?
4635                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4636                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4637                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4638                         continue;
4639                 }
4640
4641                 // fetch the lighting from the worldmodel data
4642                 VectorClear(ent->modellight_ambient);
4643                 VectorClear(ent->modellight_diffuse);
4644                 VectorClear(tempdiffusenormal);
4645                 if (ent->flags & RENDER_LIGHT)
4646                 {
4647                         vec3_t org;
4648                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4649
4650                         // complete lightning for lit sprites
4651                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4652                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4653                         {
4654                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4655                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4656                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4657                         }
4658                         else
4659                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4660
4661                         if(ent->flags & RENDER_EQUALIZE)
4662                         {
4663                                 // first fix up ambient lighting...
4664                                 if(r_equalize_entities_minambient.value > 0)
4665                                 {
4666                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4667                                         if(fd > 0)
4668                                         {
4669                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4670                                                 if(fa < r_equalize_entities_minambient.value * fd)
4671                                                 {
4672                                                         // solve:
4673                                                         //   fa'/fd' = minambient
4674                                                         //   fa'+0.25*fd' = fa+0.25*fd
4675                                                         //   ...
4676                                                         //   fa' = fd' * minambient
4677                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4678                                                         //   ...
4679                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4680                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4681                                                         //   ...
4682                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4683                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4684                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4685                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4686                                                 }
4687                                         }
4688                                 }
4689
4690                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4691                                 {
4692                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4693                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4694                                         f = fa + 0.25 * fd;
4695                                         if(f > 0)
4696                                         {
4697                                                 // adjust brightness and saturation to target
4698                                                 avg[0] = avg[1] = avg[2] = fa / f;
4699                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4700                                                 avg[0] = avg[1] = avg[2] = fd / f;
4701                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4702                                         }
4703                                 }
4704                         }
4705                 }
4706                 else // highly rare
4707                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4708
4709                 // move the light direction into modelspace coordinates for lighting code
4710                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4711                 if(VectorLength2(ent->modellight_lightdir) == 0)
4712                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4713                 VectorNormalize(ent->modellight_lightdir);
4714         }
4715 }
4716
4717 #define MAX_LINEOFSIGHTTRACES 64
4718
4719 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4720 {
4721         int i;
4722         vec3_t boxmins, boxmaxs;
4723         vec3_t start;
4724         vec3_t end;
4725         dp_model_t *model = r_refdef.scene.worldmodel;
4726
4727         if (!model || !model->brush.TraceLineOfSight)
4728                 return true;
4729
4730         // expand the box a little
4731         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4732         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4733         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4734         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4735         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4736         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4737
4738         // return true if eye is inside enlarged box
4739         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4740                 return true;
4741
4742         // try center
4743         VectorCopy(eye, start);
4744         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4745         if (model->brush.TraceLineOfSight(model, start, end))
4746                 return true;
4747
4748         // try various random positions
4749         for (i = 0;i < numsamples;i++)
4750         {
4751                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4752                 if (model->brush.TraceLineOfSight(model, start, end))
4753                         return true;
4754         }
4755
4756         return false;
4757 }
4758
4759
4760 static void R_View_UpdateEntityVisible (void)
4761 {
4762         int i;
4763         int renderimask;
4764         int samples;
4765         entity_render_t *ent;
4766
4767         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4768                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4769                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4770                 :                                                          RENDER_EXTERIORMODEL;
4771         if (!r_drawviewmodel.integer)
4772                 renderimask |= RENDER_VIEWMODEL;
4773         if (!r_drawexteriormodel.integer)
4774                 renderimask |= RENDER_EXTERIORMODEL;
4775         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4776         {
4777                 // worldmodel can check visibility
4778                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4779                 for (i = 0;i < r_refdef.scene.numentities;i++)
4780                 {
4781                         ent = r_refdef.scene.entities[i];
4782                         if (!(ent->flags & renderimask))
4783                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4784                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4785                                 r_refdef.viewcache.entityvisible[i] = true;
4786                 }
4787         }
4788         else
4789         {
4790                 // no worldmodel or it can't check visibility
4791                 for (i = 0;i < r_refdef.scene.numentities;i++)
4792                 {
4793                         ent = r_refdef.scene.entities[i];
4794                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4795                 }
4796         }
4797         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4798                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4799         {
4800                 for (i = 0;i < r_refdef.scene.numentities;i++)
4801                 {
4802                         if (!r_refdef.viewcache.entityvisible[i])
4803                                 continue;
4804                         ent = r_refdef.scene.entities[i];
4805                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4806                         {
4807                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4808                                 if (samples < 0)
4809                                         continue; // temp entities do pvs only
4810                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4811                                         ent->last_trace_visibility = realtime;
4812                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4813                                         r_refdef.viewcache.entityvisible[i] = 0;
4814                         }
4815                 }
4816         }
4817 }
4818
4819 /// only used if skyrendermasked, and normally returns false
4820 int R_DrawBrushModelsSky (void)
4821 {
4822         int i, sky;
4823         entity_render_t *ent;
4824
4825         sky = false;
4826         for (i = 0;i < r_refdef.scene.numentities;i++)
4827         {
4828                 if (!r_refdef.viewcache.entityvisible[i])
4829                         continue;
4830                 ent = r_refdef.scene.entities[i];
4831                 if (!ent->model || !ent->model->DrawSky)
4832                         continue;
4833                 ent->model->DrawSky(ent);
4834                 sky = true;
4835         }
4836         return sky;
4837 }
4838
4839 static void R_DrawNoModel(entity_render_t *ent);
4840 static void R_DrawModels(void)
4841 {
4842         int i;
4843         entity_render_t *ent;
4844
4845         for (i = 0;i < r_refdef.scene.numentities;i++)
4846         {
4847                 if (!r_refdef.viewcache.entityvisible[i])
4848                         continue;
4849                 ent = r_refdef.scene.entities[i];
4850                 r_refdef.stats.entities++;
4851                 /*
4852                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4853                 {
4854                         vec3_t f, l, u, o;
4855                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4856                         Con_Printf("R_DrawModels\n");
4857                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4858                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4859                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4860                 }
4861                 */
4862                 if (ent->model && ent->model->Draw != NULL)
4863                         ent->model->Draw(ent);
4864                 else
4865                         R_DrawNoModel(ent);
4866         }
4867 }
4868
4869 static void R_DrawModelsDepth(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 if (!r_refdef.viewcache.entityvisible[i])
4877                         continue;
4878                 ent = r_refdef.scene.entities[i];
4879                 if (ent->model && ent->model->DrawDepth != NULL)
4880                         ent->model->DrawDepth(ent);
4881         }
4882 }
4883
4884 static void R_DrawModelsDebug(void)
4885 {
4886         int i;
4887         entity_render_t *ent;
4888
4889         for (i = 0;i < r_refdef.scene.numentities;i++)
4890         {
4891                 if (!r_refdef.viewcache.entityvisible[i])
4892                         continue;
4893                 ent = r_refdef.scene.entities[i];
4894                 if (ent->model && ent->model->DrawDebug != NULL)
4895                         ent->model->DrawDebug(ent);
4896         }
4897 }
4898
4899 static void R_DrawModelsAddWaterPlanes(void)
4900 {
4901         int i;
4902         entity_render_t *ent;
4903
4904         for (i = 0;i < r_refdef.scene.numentities;i++)
4905         {
4906                 if (!r_refdef.viewcache.entityvisible[i])
4907                         continue;
4908                 ent = r_refdef.scene.entities[i];
4909                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4910                         ent->model->DrawAddWaterPlanes(ent);
4911         }
4912 }
4913
4914 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4915 {
4916         if (r_hdr_irisadaptation.integer)
4917         {
4918                 vec3_t ambient;
4919                 vec3_t diffuse;
4920                 vec3_t diffusenormal;
4921                 vec_t brightness;
4922                 vec_t goal;
4923                 vec_t adjust;
4924                 vec_t current;
4925                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4926                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4927                 brightness = max(0.0000001f, brightness);
4928                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4929                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4930                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4931                 current = r_hdr_irisadaptation_value.value;
4932                 if (current < goal)
4933                         current = min(current + adjust, goal);
4934                 else if (current > goal)
4935                         current = max(current - adjust, goal);
4936                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4937                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4938         }
4939         else if (r_hdr_irisadaptation_value.value != 1.0f)
4940                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4941 }
4942
4943 static void R_View_SetFrustum(const int *scissor)
4944 {
4945         int i;
4946         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4947         vec3_t forward, left, up, origin, v;
4948
4949         if(scissor)
4950         {
4951                 // flipped x coordinates (because x points left here)
4952                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4953                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4954
4955                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4956                 switch(vid.renderpath)
4957                 {
4958                         case RENDERPATH_D3D9:
4959                         case RENDERPATH_D3D10:
4960                         case RENDERPATH_D3D11:
4961                                 // non-flipped y coordinates
4962                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4963                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4964                                 break;
4965                         case RENDERPATH_SOFT:
4966                         case RENDERPATH_GL11:
4967                         case RENDERPATH_GL13:
4968                         case RENDERPATH_GL20:
4969                         case RENDERPATH_GLES1:
4970                         case RENDERPATH_GLES2:
4971                                 // non-flipped y coordinates
4972                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4973                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4974                                 break;
4975                 }
4976         }
4977
4978         // we can't trust r_refdef.view.forward and friends in reflected scenes
4979         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4980
4981 #if 0
4982         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4983         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4984         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4985         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4986         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4987         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4988         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4989         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4990         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4991         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4992         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4993         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4994 #endif
4995
4996 #if 0
4997         zNear = r_refdef.nearclip;
4998         nudge = 1.0 - 1.0 / (1<<23);
4999         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5000         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5001         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5002         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5003         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5004         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5005         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5006         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5007 #endif
5008
5009
5010
5011 #if 0
5012         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5013         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5014         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5015         r_refdef.view.frustum[0].dist = m[15] - m[12];
5016
5017         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5018         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5019         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5020         r_refdef.view.frustum[1].dist = m[15] + m[12];
5021
5022         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5023         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5024         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5025         r_refdef.view.frustum[2].dist = m[15] - m[13];
5026
5027         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5028         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5029         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5030         r_refdef.view.frustum[3].dist = m[15] + m[13];
5031
5032         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5033         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5034         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5035         r_refdef.view.frustum[4].dist = m[15] - m[14];
5036
5037         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5038         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5039         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5040         r_refdef.view.frustum[5].dist = m[15] + m[14];
5041 #endif
5042
5043         if (r_refdef.view.useperspective)
5044         {
5045                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5046                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5047                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5048                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5049                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5050
5051                 // then the normals from the corners relative to origin
5052                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5053                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5054                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5055                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5056
5057                 // in a NORMAL view, forward cross left == up
5058                 // in a REFLECTED view, forward cross left == down
5059                 // so our cross products above need to be adjusted for a left handed coordinate system
5060                 CrossProduct(forward, left, v);
5061                 if(DotProduct(v, up) < 0)
5062                 {
5063                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5064                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5065                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5066                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5067                 }
5068
5069                 // Leaving those out was a mistake, those were in the old code, and they
5070                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5071                 // I couldn't reproduce it after adding those normalizations. --blub
5072                 VectorNormalize(r_refdef.view.frustum[0].normal);
5073                 VectorNormalize(r_refdef.view.frustum[1].normal);
5074                 VectorNormalize(r_refdef.view.frustum[2].normal);
5075                 VectorNormalize(r_refdef.view.frustum[3].normal);
5076
5077                 // make the corners absolute
5078                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5079                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5080                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5081                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5082
5083                 // one more normal
5084                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5085
5086                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5087                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5088                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5089                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5090                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5091         }
5092         else
5093         {
5094                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5095                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5096                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5097                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5098                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5099                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5100                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5101                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5102                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5103                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5104         }
5105         r_refdef.view.numfrustumplanes = 5;
5106
5107         if (r_refdef.view.useclipplane)
5108         {
5109                 r_refdef.view.numfrustumplanes = 6;
5110                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5111         }
5112
5113         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5114                 PlaneClassify(r_refdef.view.frustum + i);
5115
5116         // LordHavoc: note to all quake engine coders, Quake had a special case
5117         // for 90 degrees which assumed a square view (wrong), so I removed it,
5118         // Quake2 has it disabled as well.
5119
5120         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5121         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5122         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5123         //PlaneClassify(&frustum[0]);
5124
5125         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5126         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5127         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5128         //PlaneClassify(&frustum[1]);
5129
5130         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5131         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5132         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5133         //PlaneClassify(&frustum[2]);
5134
5135         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5136         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5137         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5138         //PlaneClassify(&frustum[3]);
5139
5140         // nearclip plane
5141         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5142         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5143         //PlaneClassify(&frustum[4]);
5144 }
5145
5146 void R_View_UpdateWithScissor(const int *myscissor)
5147 {
5148         R_Main_ResizeViewCache();
5149         R_View_SetFrustum(myscissor);
5150         R_View_WorldVisibility(r_refdef.view.useclipplane);
5151         R_View_UpdateEntityVisible();
5152         R_View_UpdateEntityLighting();
5153 }
5154
5155 void R_View_Update(void)
5156 {
5157         R_Main_ResizeViewCache();
5158         R_View_SetFrustum(NULL);
5159         R_View_WorldVisibility(r_refdef.view.useclipplane);
5160         R_View_UpdateEntityVisible();
5161         R_View_UpdateEntityLighting();
5162 }
5163
5164 float viewscalefpsadjusted = 1.0f;
5165
5166 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5167 {
5168         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5169         scale = bound(0.03125f, scale, 1.0f);
5170         *outwidth = (int)ceil(width * scale);
5171         *outheight = (int)ceil(height * scale);
5172 }
5173
5174 void R_Mesh_SetMainRenderTargets(void)
5175 {
5176         if (r_bloomstate.fbo_framebuffer)
5177                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5178         else
5179                 R_Mesh_ResetRenderTargets();
5180 }
5181
5182 void R_SetupView(qboolean allowwaterclippingplane)
5183 {
5184         const float *customclipplane = NULL;
5185         float plane[4];
5186         int scaledwidth, scaledheight;
5187         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5188         {
5189                 // LordHavoc: couldn't figure out how to make this approach the
5190                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5191                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5192                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5193                         dist = r_refdef.view.clipplane.dist;
5194                 plane[0] = r_refdef.view.clipplane.normal[0];
5195                 plane[1] = r_refdef.view.clipplane.normal[1];
5196                 plane[2] = r_refdef.view.clipplane.normal[2];
5197                 plane[3] = -dist;
5198                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5199         }
5200
5201         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5202         if (!r_refdef.view.useperspective)
5203                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5204         else if (vid.stencil && r_useinfinitefarclip.integer)
5205                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5206         else
5207                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5208         R_Mesh_SetMainRenderTargets();
5209         R_SetViewport(&r_refdef.view.viewport);
5210         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5211         {
5212                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5213                 float screenplane[4];
5214                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5215                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5216                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5217                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5218                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5219         }
5220 }
5221
5222 void R_EntityMatrix(const matrix4x4_t *matrix)
5223 {
5224         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5225         {
5226                 gl_modelmatrixchanged = false;
5227                 gl_modelmatrix = *matrix;
5228                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5229                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5230                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5231                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5232                 CHECKGLERROR
5233                 switch(vid.renderpath)
5234                 {
5235                 case RENDERPATH_D3D9:
5236 #ifdef SUPPORTD3D
5237                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5238                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5239 #endif
5240                         break;
5241                 case RENDERPATH_D3D10:
5242                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5243                         break;
5244                 case RENDERPATH_D3D11:
5245                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5246                         break;
5247                 case RENDERPATH_GL11:
5248                 case RENDERPATH_GL13:
5249                 case RENDERPATH_GLES1:
5250                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5251                         break;
5252                 case RENDERPATH_SOFT:
5253                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5254                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5255                         break;
5256                 case RENDERPATH_GL20:
5257                 case RENDERPATH_GLES2:
5258                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5259                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5260                         break;
5261                 }
5262         }
5263 }
5264
5265 void R_ResetViewRendering2D(void)
5266 {
5267         r_viewport_t viewport;
5268         DrawQ_Finish();
5269
5270         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5271         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5272         R_Mesh_ResetRenderTargets();
5273         R_SetViewport(&viewport);
5274         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5275         GL_Color(1, 1, 1, 1);
5276         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5277         GL_BlendFunc(GL_ONE, GL_ZERO);
5278         GL_ScissorTest(false);
5279         GL_DepthMask(false);
5280         GL_DepthRange(0, 1);
5281         GL_DepthTest(false);
5282         GL_DepthFunc(GL_LEQUAL);
5283         R_EntityMatrix(&identitymatrix);
5284         R_Mesh_ResetTextureState();
5285         GL_PolygonOffset(0, 0);
5286         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5287         switch(vid.renderpath)
5288         {
5289         case RENDERPATH_GL11:
5290         case RENDERPATH_GL13:
5291         case RENDERPATH_GL20:
5292         case RENDERPATH_GLES1:
5293         case RENDERPATH_GLES2:
5294                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5295                 break;
5296         case RENDERPATH_D3D9:
5297         case RENDERPATH_D3D10:
5298         case RENDERPATH_D3D11:
5299         case RENDERPATH_SOFT:
5300                 break;
5301         }
5302         GL_CullFace(GL_NONE);
5303 }
5304
5305 void R_ResetViewRendering3D(void)
5306 {
5307         DrawQ_Finish();
5308
5309         R_SetupView(true);
5310         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5311         GL_Color(1, 1, 1, 1);
5312         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5313         GL_BlendFunc(GL_ONE, GL_ZERO);
5314         GL_ScissorTest(true);
5315         GL_DepthMask(true);
5316         GL_DepthRange(0, 1);
5317         GL_DepthTest(true);
5318         GL_DepthFunc(GL_LEQUAL);
5319         R_EntityMatrix(&identitymatrix);
5320         R_Mesh_ResetTextureState();
5321         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5322         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5323         switch(vid.renderpath)
5324         {
5325         case RENDERPATH_GL11:
5326         case RENDERPATH_GL13:
5327         case RENDERPATH_GL20:
5328         case RENDERPATH_GLES1:
5329         case RENDERPATH_GLES2:
5330                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5331                 break;
5332         case RENDERPATH_D3D9:
5333         case RENDERPATH_D3D10:
5334         case RENDERPATH_D3D11:
5335         case RENDERPATH_SOFT:
5336                 break;
5337         }
5338         GL_CullFace(r_refdef.view.cullface_back);
5339 }
5340
5341 /*
5342 ================
5343 R_RenderView_UpdateViewVectors
5344 ================
5345 */
5346 static void R_RenderView_UpdateViewVectors(void)
5347 {
5348         // break apart the view matrix into vectors for various purposes
5349         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5350         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5351         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5352         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5353         // make an inverted copy of the view matrix for tracking sprites
5354         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5355 }
5356
5357 void R_RenderScene(void);
5358 void R_RenderWaterPlanes(void);
5359
5360 static void R_Water_StartFrame(void)
5361 {
5362         int i;
5363         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5364         r_waterstate_waterplane_t *p;
5365
5366         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5367                 return;
5368
5369         switch(vid.renderpath)
5370         {
5371         case RENDERPATH_GL20:
5372         case RENDERPATH_D3D9:
5373         case RENDERPATH_D3D10:
5374         case RENDERPATH_D3D11:
5375         case RENDERPATH_SOFT:
5376         case RENDERPATH_GLES2:
5377                 break;
5378         case RENDERPATH_GL11:
5379         case RENDERPATH_GL13:
5380         case RENDERPATH_GLES1:
5381                 return;
5382         }
5383
5384         // set waterwidth and waterheight to the water resolution that will be
5385         // used (often less than the screen resolution for faster rendering)
5386         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5387
5388         // calculate desired texture sizes
5389         // can't use water if the card does not support the texture size
5390         if (!r_water.integer || r_showsurfaces.integer)
5391                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5392         else if (vid.support.arb_texture_non_power_of_two)
5393         {
5394                 texturewidth = waterwidth;
5395                 textureheight = waterheight;
5396                 camerawidth = waterwidth;
5397                 cameraheight = waterheight;
5398         }
5399         else
5400         {
5401                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5402                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5403                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5404                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5405         }
5406
5407         // allocate textures as needed
5408         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5409         {
5410                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5411                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5412                 {
5413                         if (p->texture_refraction)
5414                                 R_FreeTexture(p->texture_refraction);
5415                         p->texture_refraction = NULL;
5416                         if (p->texture_reflection)
5417                                 R_FreeTexture(p->texture_reflection);
5418                         p->texture_reflection = NULL;
5419                         if (p->texture_camera)
5420                                 R_FreeTexture(p->texture_camera);
5421                         p->texture_camera = NULL;
5422                 }
5423                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5424                 r_waterstate.texturewidth = texturewidth;
5425                 r_waterstate.textureheight = textureheight;
5426                 r_waterstate.camerawidth = camerawidth;
5427                 r_waterstate.cameraheight = cameraheight;
5428         }
5429
5430         if (r_waterstate.texturewidth)
5431         {
5432                 int scaledwidth, scaledheight;
5433
5434                 r_waterstate.enabled = true;
5435
5436                 // when doing a reduced render (HDR) we want to use a smaller area
5437                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5438                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5439                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5440
5441                 // set up variables that will be used in shader setup
5442                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5443                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5444                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5445                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5446         }
5447
5448         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5449         r_waterstate.numwaterplanes = 0;
5450 }
5451
5452 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5453 {
5454         int triangleindex, planeindex;
5455         const int *e;
5456         vec3_t vert[3];
5457         vec3_t normal;
5458         vec3_t center;
5459         mplane_t plane;
5460         r_waterstate_waterplane_t *p;
5461         texture_t *t = R_GetCurrentTexture(surface->texture);
5462
5463         // just use the first triangle with a valid normal for any decisions
5464         VectorClear(normal);
5465         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5466         {
5467                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5468                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5469                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5470                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5471                 if (VectorLength2(normal) >= 0.001)
5472                         break;
5473         }
5474
5475         VectorCopy(normal, plane.normal);
5476         VectorNormalize(plane.normal);
5477         plane.dist = DotProduct(vert[0], plane.normal);
5478         PlaneClassify(&plane);
5479         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5480         {
5481                 // skip backfaces (except if nocullface is set)
5482                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5483                         return;
5484                 VectorNegate(plane.normal, plane.normal);
5485                 plane.dist *= -1;
5486                 PlaneClassify(&plane);
5487         }
5488
5489
5490         // find a matching plane if there is one
5491         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5492                 if(p->camera_entity == t->camera_entity)
5493                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5494                                 break;
5495         if (planeindex >= r_waterstate.maxwaterplanes)
5496                 return; // nothing we can do, out of planes
5497
5498         // if this triangle does not fit any known plane rendered this frame, add one
5499         if (planeindex >= r_waterstate.numwaterplanes)
5500         {
5501                 // store the new plane
5502                 r_waterstate.numwaterplanes++;
5503                 p->plane = plane;
5504                 // clear materialflags and pvs
5505                 p->materialflags = 0;
5506                 p->pvsvalid = false;
5507                 p->camera_entity = t->camera_entity;
5508                 VectorCopy(surface->mins, p->mins);
5509                 VectorCopy(surface->maxs, p->maxs);
5510         }
5511         else
5512         {
5513                 // merge mins/maxs
5514                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5515                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5516                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5517                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5518                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5519                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5520         }
5521         // merge this surface's materialflags into the waterplane
5522         p->materialflags |= t->currentmaterialflags;
5523         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5524         {
5525                 // merge this surface's PVS into the waterplane
5526                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5527                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5528                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5529                 {
5530                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5531                         p->pvsvalid = true;
5532                 }
5533         }
5534 }
5535
5536 extern cvar_t r_drawparticles;
5537 extern cvar_t r_drawdecals;
5538
5539 static void R_Water_ProcessPlanes(void)
5540 {
5541         int myscissor[4];
5542         r_refdef_view_t originalview;
5543         r_refdef_view_t myview;
5544         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5545         r_waterstate_waterplane_t *p;
5546         vec3_t visorigin;
5547
5548         originalview = r_refdef.view;
5549
5550         // lowquality hack, temporarily shut down some cvars and restore afterwards
5551         qualityreduction = r_water_lowquality.integer;
5552         if (qualityreduction > 0)
5553         {
5554                 if (qualityreduction >= 1)
5555                 {
5556                         old_r_shadows = r_shadows.integer;
5557                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5558                         old_r_dlight = r_shadow_realtime_dlight.integer;
5559                         Cvar_SetValueQuick(&r_shadows, 0);
5560                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5561                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5562                 }
5563                 if (qualityreduction >= 2)
5564                 {
5565                         old_r_dynamic = r_dynamic.integer;
5566                         old_r_particles = r_drawparticles.integer;
5567                         old_r_decals = r_drawdecals.integer;
5568                         Cvar_SetValueQuick(&r_dynamic, 0);
5569                         Cvar_SetValueQuick(&r_drawparticles, 0);
5570                         Cvar_SetValueQuick(&r_drawdecals, 0);
5571                 }
5572         }
5573
5574         // make sure enough textures are allocated
5575         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5576         {
5577                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5578                 {
5579                         if (!p->texture_refraction)
5580                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5581                         if (!p->texture_refraction)
5582                                 goto error;
5583                 }
5584                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5585                 {
5586                         if (!p->texture_camera)
5587                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5588                         if (!p->texture_camera)
5589                                 goto error;
5590                 }
5591
5592                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5593                 {
5594                         if (!p->texture_reflection)
5595                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5596                         if (!p->texture_reflection)
5597                                 goto error;
5598                 }
5599         }
5600
5601         // render views
5602         r_refdef.view = originalview;
5603         r_refdef.view.showdebug = false;
5604         r_refdef.view.width = r_waterstate.waterwidth;
5605         r_refdef.view.height = r_waterstate.waterheight;
5606         r_refdef.view.useclipplane = true;
5607         myview = r_refdef.view;
5608         r_waterstate.renderingscene = true;
5609         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5610         {
5611                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5612                 {
5613                         r_refdef.view = myview;
5614                         if(r_water_scissormode.integer)
5615                         {
5616                                 R_SetupView(true);
5617                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5618                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5619                         }
5620
5621                         // render reflected scene and copy into texture
5622                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5623                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5624                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5625                         r_refdef.view.clipplane = p->plane;
5626                         // reverse the cullface settings for this render
5627                         r_refdef.view.cullface_front = GL_FRONT;
5628                         r_refdef.view.cullface_back = GL_BACK;
5629                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5630                         {
5631                                 r_refdef.view.usecustompvs = true;
5632                                 if (p->pvsvalid)
5633                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5634                                 else
5635                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5636                         }
5637
5638                         R_ResetViewRendering3D();
5639                         R_ClearScreen(r_refdef.fogenabled);
5640                         if(r_water_scissormode.integer & 2)
5641                                 R_View_UpdateWithScissor(myscissor);
5642                         else
5643                                 R_View_Update();
5644                         if(r_water_scissormode.integer & 1)
5645                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5646                         R_RenderScene();
5647
5648                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5649                 }
5650
5651                 // render the normal view scene and copy into texture
5652                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5653                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5654                 {
5655                         r_refdef.view = myview;
5656                         if(r_water_scissormode.integer)
5657                         {
5658                                 R_SetupView(true);
5659                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5660                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5661                         }
5662
5663                         r_waterstate.renderingrefraction = true;
5664
5665                         r_refdef.view.clipplane = p->plane;
5666                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5667                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5668
5669                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5670                         {
5671                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5672                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5673                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5674                                 R_RenderView_UpdateViewVectors();
5675                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5676                                 {
5677                                         r_refdef.view.usecustompvs = true;
5678                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5679                                 }
5680                         }
5681
5682                         PlaneClassify(&r_refdef.view.clipplane);
5683
5684                         R_ResetViewRendering3D();
5685                         R_ClearScreen(r_refdef.fogenabled);
5686                         if(r_water_scissormode.integer & 2)
5687                                 R_View_UpdateWithScissor(myscissor);
5688                         else
5689                                 R_View_Update();
5690                         if(r_water_scissormode.integer & 1)
5691                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5692                         R_RenderScene();
5693
5694                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5695                         r_waterstate.renderingrefraction = false;
5696                 }
5697                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5698                 {
5699                         r_refdef.view = myview;
5700
5701                         r_refdef.view.clipplane = p->plane;
5702                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5703                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5704
5705                         r_refdef.view.width = r_waterstate.camerawidth;
5706                         r_refdef.view.height = r_waterstate.cameraheight;
5707                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5708                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5709
5710                         if(p->camera_entity)
5711                         {
5712                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5713                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5714                         }
5715
5716                         // note: all of the view is used for displaying... so
5717                         // there is no use in scissoring
5718
5719                         // reverse the cullface settings for this render
5720                         r_refdef.view.cullface_front = GL_FRONT;
5721                         r_refdef.view.cullface_back = GL_BACK;
5722                         // also reverse the view matrix
5723                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5724                         R_RenderView_UpdateViewVectors();
5725                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5726                         {
5727                                 r_refdef.view.usecustompvs = true;
5728                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5729                         }
5730                         
5731                         // camera needs no clipplane
5732                         r_refdef.view.useclipplane = false;
5733
5734                         PlaneClassify(&r_refdef.view.clipplane);
5735
5736                         R_ResetViewRendering3D();
5737                         R_ClearScreen(r_refdef.fogenabled);
5738                         R_View_Update();
5739                         R_RenderScene();
5740
5741                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5742                         r_waterstate.renderingrefraction = false;
5743                 }
5744
5745         }
5746         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5747         r_waterstate.renderingscene = false;
5748         r_refdef.view = originalview;
5749         R_ResetViewRendering3D();
5750         R_ClearScreen(r_refdef.fogenabled);
5751         R_View_Update();
5752         goto finish;
5753 error:
5754         r_refdef.view = originalview;
5755         r_waterstate.renderingscene = false;
5756         Cvar_SetValueQuick(&r_water, 0);
5757         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5758 finish:
5759         // lowquality hack, restore cvars
5760         if (qualityreduction > 0)
5761         {
5762                 if (qualityreduction >= 1)
5763                 {
5764                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5765                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5766                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5767                 }
5768                 if (qualityreduction >= 2)
5769                 {
5770                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5771                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5772                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5773                 }
5774         }
5775 }
5776
5777 void R_Bloom_StartFrame(void)
5778 {
5779         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5780         int viewwidth, viewheight;
5781         textype_t textype;
5782
5783         if (r_viewscale_fpsscaling.integer)
5784         {
5785                 double actualframetime;
5786                 double targetframetime;
5787                 double adjust;
5788                 actualframetime = r_refdef.lastdrawscreentime;
5789                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5790                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5791                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5792                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5793                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5794                 viewscalefpsadjusted += adjust;
5795                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5796         }
5797         else
5798                 viewscalefpsadjusted = 1.0f;
5799
5800         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5801
5802         switch(vid.renderpath)
5803         {
5804         case RENDERPATH_GL20:
5805         case RENDERPATH_D3D9:
5806         case RENDERPATH_D3D10:
5807         case RENDERPATH_D3D11:
5808         case RENDERPATH_SOFT:
5809         case RENDERPATH_GLES2:
5810                 break;
5811         case RENDERPATH_GL11:
5812         case RENDERPATH_GL13:
5813         case RENDERPATH_GLES1:
5814                 return;
5815         }
5816
5817         // set bloomwidth and bloomheight to the bloom resolution that will be
5818         // used (often less than the screen resolution for faster rendering)
5819         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5820         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5821         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5822         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5823         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5824
5825         // calculate desired texture sizes
5826         if (vid.support.arb_texture_non_power_of_two)
5827         {
5828                 screentexturewidth = vid.width;
5829                 screentextureheight = vid.height;
5830                 bloomtexturewidth = r_bloomstate.bloomwidth;
5831                 bloomtextureheight = r_bloomstate.bloomheight;
5832         }
5833         else
5834         {
5835                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5836                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5837                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5838                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5839         }
5840
5841         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5842         {
5843                 Cvar_SetValueQuick(&r_hdr, 0);
5844                 Cvar_SetValueQuick(&r_bloom, 0);
5845                 Cvar_SetValueQuick(&r_motionblur, 0);
5846                 Cvar_SetValueQuick(&r_damageblur, 0);
5847         }
5848
5849         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5850                 screentexturewidth = screentextureheight = 0;
5851         if (!r_hdr.integer && !r_bloom.integer)
5852                 bloomtexturewidth = bloomtextureheight = 0;
5853
5854         textype = TEXTYPE_COLORBUFFER;
5855         switch (vid.renderpath)
5856         {
5857         case RENDERPATH_GL20:
5858         case RENDERPATH_GLES2:
5859                 if (vid.support.ext_framebuffer_object)
5860                 {
5861                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5862                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5863                 }
5864                 break;
5865         case RENDERPATH_GL11:
5866         case RENDERPATH_GL13:
5867         case RENDERPATH_GLES1:
5868         case RENDERPATH_D3D9:
5869         case RENDERPATH_D3D10:
5870         case RENDERPATH_D3D11:
5871         case RENDERPATH_SOFT:
5872                 break;
5873         }
5874
5875         // allocate textures as needed
5876         if (r_bloomstate.screentexturewidth != screentexturewidth
5877          || r_bloomstate.screentextureheight != screentextureheight
5878          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5879          || r_bloomstate.bloomtextureheight != bloomtextureheight
5880          || r_bloomstate.texturetype != textype
5881          || r_bloomstate.viewfbo != r_viewfbo.integer)
5882         {
5883                 if (r_bloomstate.texture_bloom)
5884                         R_FreeTexture(r_bloomstate.texture_bloom);
5885                 r_bloomstate.texture_bloom = NULL;
5886                 if (r_bloomstate.texture_screen)
5887                         R_FreeTexture(r_bloomstate.texture_screen);
5888                 r_bloomstate.texture_screen = NULL;
5889                 if (r_bloomstate.fbo_framebuffer)
5890                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5891                 r_bloomstate.fbo_framebuffer = 0;
5892                 if (r_bloomstate.texture_framebuffercolor)
5893                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5894                 r_bloomstate.texture_framebuffercolor = NULL;
5895                 if (r_bloomstate.texture_framebufferdepth)
5896                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5897                 r_bloomstate.texture_framebufferdepth = NULL;
5898                 r_bloomstate.screentexturewidth = screentexturewidth;
5899                 r_bloomstate.screentextureheight = screentextureheight;
5900                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5901                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5902                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5903                 {
5904                         // FIXME: choose depth bits based on a cvar
5905                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5906                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5907                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5908                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5909                         // render depth into one texture and normalmap into the other
5910                         if (qglDrawBuffer)
5911                         {
5912                                 int status;
5913                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5914                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5915                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5916                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5917                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5918                         }
5919                 }
5920                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5921                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5922                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5923                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5924                 r_bloomstate.viewfbo = r_viewfbo.integer;
5925                 r_bloomstate.texturetype = textype;
5926         }
5927
5928         // when doing a reduced render (HDR) we want to use a smaller area
5929         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5930         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5931         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5932         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5933         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5934
5935         // set up a texcoord array for the full resolution screen image
5936         // (we have to keep this around to copy back during final render)
5937         r_bloomstate.screentexcoord2f[0] = 0;
5938         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5939         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5940         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5941         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5942         r_bloomstate.screentexcoord2f[5] = 0;
5943         r_bloomstate.screentexcoord2f[6] = 0;
5944         r_bloomstate.screentexcoord2f[7] = 0;
5945
5946         // set up a texcoord array for the reduced resolution bloom image
5947         // (which will be additive blended over the screen image)
5948         r_bloomstate.bloomtexcoord2f[0] = 0;
5949         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5950         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5951         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5952         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5953         r_bloomstate.bloomtexcoord2f[5] = 0;
5954         r_bloomstate.bloomtexcoord2f[6] = 0;
5955         r_bloomstate.bloomtexcoord2f[7] = 0;
5956
5957         switch(vid.renderpath)
5958         {
5959         case RENDERPATH_GL11:
5960         case RENDERPATH_GL13:
5961         case RENDERPATH_GL20:
5962         case RENDERPATH_SOFT:
5963         case RENDERPATH_GLES1:
5964         case RENDERPATH_GLES2:
5965                 break;
5966         case RENDERPATH_D3D9:
5967         case RENDERPATH_D3D10:
5968         case RENDERPATH_D3D11:
5969                 {
5970                         int i;
5971                         for (i = 0;i < 4;i++)
5972                         {
5973                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5974                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5975                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5976                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5977                         }
5978                 }
5979                 break;
5980         }
5981
5982         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5983         {
5984                 r_bloomstate.enabled = true;
5985                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5986         }
5987
5988         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5989
5990         if (r_bloomstate.fbo_framebuffer)
5991                 r_refdef.view.clear = true;
5992 }
5993
5994 void R_Bloom_CopyBloomTexture(float colorscale)
5995 {
5996         r_refdef.stats.bloom++;
5997
5998         // scale down screen texture to the bloom texture size
5999         CHECKGLERROR
6000         R_Mesh_SetMainRenderTargets();
6001         R_SetViewport(&r_bloomstate.viewport);
6002         GL_BlendFunc(GL_ONE, GL_ZERO);
6003         GL_Color(colorscale, colorscale, colorscale, 1);
6004         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6005         switch(vid.renderpath)
6006         {
6007         case RENDERPATH_GL11:
6008         case RENDERPATH_GL13:
6009         case RENDERPATH_GL20:
6010         case RENDERPATH_GLES1:
6011         case RENDERPATH_GLES2:
6012         case RENDERPATH_SOFT:
6013                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6014                 break;
6015         case RENDERPATH_D3D9:
6016         case RENDERPATH_D3D10:
6017         case RENDERPATH_D3D11:
6018                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6019                 break;
6020         }
6021         // TODO: do boxfilter scale-down in shader?
6022         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6023         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6024         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6025
6026         // we now have a bloom image in the framebuffer
6027         // copy it into the bloom image texture for later processing
6028         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6029         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6030 }
6031
6032 void R_Bloom_CopyHDRTexture(void)
6033 {
6034         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6035         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6036 }
6037
6038 void R_Bloom_MakeTexture(void)
6039 {
6040         int x, range, dir;
6041         float xoffset, yoffset, r, brighten;
6042
6043         r_refdef.stats.bloom++;
6044
6045         R_ResetViewRendering2D();
6046
6047         // we have a bloom image in the framebuffer
6048         CHECKGLERROR
6049         R_SetViewport(&r_bloomstate.viewport);
6050
6051         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6052         {
6053                 x *= 2;
6054                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6055                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6056                 GL_Color(r,r,r,1);
6057                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6058                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6059                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6060                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6061
6062                 // copy the vertically blurred bloom view to a texture
6063                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6064                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6065         }
6066
6067         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6068         brighten = r_bloom_brighten.value;
6069         if (r_bloomstate.hdr)
6070                 brighten *= r_hdr_range.value;
6071         brighten = sqrt(brighten);
6072         if(range >= 1)
6073                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6074         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6075
6076         for (dir = 0;dir < 2;dir++)
6077         {
6078                 // blend on at multiple vertical offsets to achieve a vertical blur
6079                 // TODO: do offset blends using GLSL
6080                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6081                 GL_BlendFunc(GL_ONE, GL_ZERO);
6082                 for (x = -range;x <= range;x++)
6083                 {
6084                         if (!dir){xoffset = 0;yoffset = x;}
6085                         else {xoffset = x;yoffset = 0;}
6086                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6087                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6088                         // compute a texcoord array with the specified x and y offset
6089                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6090                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6091                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6092                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6093                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6094                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6095                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6096                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6097                         // this r value looks like a 'dot' particle, fading sharply to
6098                         // black at the edges
6099                         // (probably not realistic but looks good enough)
6100                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6101                         //r = brighten/(range*2+1);
6102                         r = brighten / (range * 2 + 1);
6103                         if(range >= 1)
6104                                 r *= (1 - x*x/(float)(range*range));
6105                         GL_Color(r, r, r, 1);
6106                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6107                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6108                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6109                         GL_BlendFunc(GL_ONE, GL_ONE);
6110                 }
6111
6112                 // copy the vertically blurred bloom view to a texture
6113                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6114                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6115         }
6116 }
6117
6118 void R_HDR_RenderBloomTexture(void)
6119 {
6120         int oldwidth, oldheight;
6121         float oldcolorscale;
6122         qboolean oldwaterstate;
6123
6124         oldwaterstate = r_waterstate.enabled;
6125         oldcolorscale = r_refdef.view.colorscale;
6126         oldwidth = r_refdef.view.width;
6127         oldheight = r_refdef.view.height;
6128         r_refdef.view.width = r_bloomstate.bloomwidth;
6129         r_refdef.view.height = r_bloomstate.bloomheight;
6130
6131         if(r_hdr.integer < 2)
6132                 r_waterstate.enabled = false;
6133
6134         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6135         // TODO: add exposure compensation features
6136         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6137
6138         r_refdef.view.showdebug = false;
6139         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6140
6141         R_ResetViewRendering3D();
6142
6143         R_ClearScreen(r_refdef.fogenabled);
6144         if (r_timereport_active)
6145                 R_TimeReport("HDRclear");
6146
6147         R_View_Update();
6148         if (r_timereport_active)
6149                 R_TimeReport("visibility");
6150
6151         // only do secondary renders with HDR if r_hdr is 2 or higher
6152         r_waterstate.numwaterplanes = 0;
6153         if (r_waterstate.enabled)
6154                 R_RenderWaterPlanes();
6155
6156         r_refdef.view.showdebug = true;
6157         R_RenderScene();
6158         r_waterstate.numwaterplanes = 0;
6159
6160         R_ResetViewRendering2D();
6161
6162         R_Bloom_CopyHDRTexture();
6163         R_Bloom_MakeTexture();
6164
6165         // restore the view settings
6166         r_waterstate.enabled = oldwaterstate;
6167         r_refdef.view.width = oldwidth;
6168         r_refdef.view.height = oldheight;
6169         r_refdef.view.colorscale = oldcolorscale;
6170
6171         R_ResetViewRendering3D();
6172
6173         R_ClearScreen(r_refdef.fogenabled);
6174         if (r_timereport_active)
6175                 R_TimeReport("viewclear");
6176 }
6177
6178 static void R_BlendView(void)
6179 {
6180         unsigned int permutation;
6181         float uservecs[4][4];
6182
6183         switch (vid.renderpath)
6184         {
6185         case RENDERPATH_GL20:
6186         case RENDERPATH_D3D9:
6187         case RENDERPATH_D3D10:
6188         case RENDERPATH_D3D11:
6189         case RENDERPATH_SOFT:
6190         case RENDERPATH_GLES2:
6191                 permutation =
6192                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6193                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6194                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6195                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6196                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6197
6198                 if (r_bloomstate.texture_screen)
6199                 {
6200                         // make sure the buffer is available
6201                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6202
6203                         R_ResetViewRendering2D();
6204                         R_Mesh_SetMainRenderTargets();
6205
6206                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6207                         {
6208                                 // declare variables
6209                                 float speed;
6210                                 static float avgspeed;
6211
6212                                 speed = VectorLength(cl.movement_velocity);
6213
6214                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6215                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6216
6217                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6218                                 speed = bound(0, speed, 1);
6219                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6220
6221                                 // calculate values into a standard alpha
6222                                 cl.motionbluralpha = 1 - exp(-
6223                                                 (
6224                                                  (r_motionblur.value * speed / 80)
6225                                                  +
6226                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6227                                                 )
6228                                                 /
6229                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6230                                            );
6231
6232                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6233                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6234                                 // apply the blur
6235                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6236                                 {
6237                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6238                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6239                                         switch(vid.renderpath)
6240                                         {
6241                                         case RENDERPATH_GL11:
6242                                         case RENDERPATH_GL13:
6243                                         case RENDERPATH_GL20:
6244                                         case RENDERPATH_GLES1:
6245                                         case RENDERPATH_GLES2:
6246                                         case RENDERPATH_SOFT:
6247                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6248                                                 break;
6249                                         case RENDERPATH_D3D9:
6250                                         case RENDERPATH_D3D10:
6251                                         case RENDERPATH_D3D11:
6252                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6253                                                 break;
6254                                         }
6255                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6256                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6257                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6258                                 }
6259                         }
6260
6261                         // copy view into the screen texture
6262                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6263                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6264                 }
6265                 else if (!r_bloomstate.texture_bloom)
6266                 {
6267                         // we may still have to do view tint...
6268                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6269                         {
6270                                 // apply a color tint to the whole view
6271                                 R_ResetViewRendering2D();
6272                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6273                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6274                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6275                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6276                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6277                         }
6278                         break; // no screen processing, no bloom, skip it
6279                 }
6280
6281                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6282                 {
6283                         // render simple bloom effect
6284                         // copy the screen and shrink it and darken it for the bloom process
6285                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6286                         // make the bloom texture
6287                         R_Bloom_MakeTexture();
6288                 }
6289
6290 #if _MSC_VER >= 1400
6291 #define sscanf sscanf_s
6292 #endif
6293                 memset(uservecs, 0, sizeof(uservecs));
6294                 if (r_glsl_postprocess_uservec1_enable.integer)
6295                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6296                 if (r_glsl_postprocess_uservec2_enable.integer)
6297                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6298                 if (r_glsl_postprocess_uservec3_enable.integer)
6299                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6300                 if (r_glsl_postprocess_uservec4_enable.integer)
6301                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6302
6303                 R_ResetViewRendering2D();
6304                 GL_Color(1, 1, 1, 1);
6305                 GL_BlendFunc(GL_ONE, GL_ZERO);
6306
6307                 switch(vid.renderpath)
6308                 {
6309                 case RENDERPATH_GL20:
6310                 case RENDERPATH_GLES2:
6311                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6312                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6313                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6314                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6315                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6316                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6317                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6318                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6319                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6320                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6321                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6322                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6323                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6324                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6325                         break;
6326                 case RENDERPATH_D3D9:
6327 #ifdef SUPPORTD3D
6328                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6329                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6330                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6331                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6332                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6333                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6334                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6335                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6336                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6337                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6338                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6339                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6340                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6341                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6342                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6343 #endif
6344                         break;
6345                 case RENDERPATH_D3D10:
6346                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6347                         break;
6348                 case RENDERPATH_D3D11:
6349                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6350                         break;
6351                 case RENDERPATH_SOFT:
6352                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6353                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6354                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6355                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6356                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6357                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6358                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6359                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6360                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6361                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6362                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6363                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6364                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6365                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6366                         break;
6367                 default:
6368                         break;
6369                 }
6370                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6371                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6372                 break;
6373         case RENDERPATH_GL11:
6374         case RENDERPATH_GL13:
6375         case RENDERPATH_GLES1:
6376                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6377                 {
6378                         // apply a color tint to the whole view
6379                         R_ResetViewRendering2D();
6380                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6381                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6382                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6383                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6384                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6385                 }
6386                 break;
6387         }
6388 }
6389
6390 matrix4x4_t r_waterscrollmatrix;
6391
6392 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6393 {
6394         if (r_refdef.fog_density)
6395         {
6396                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6397                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6398                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6399
6400                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6401                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6402                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6403                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6404
6405                 {
6406                         vec3_t fogvec;
6407                         VectorCopy(r_refdef.fogcolor, fogvec);
6408                         //   color.rgb *= ContrastBoost * SceneBrightness;
6409                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6410                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6411                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6412                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6413                 }
6414         }
6415 }
6416
6417 void R_UpdateVariables(void)
6418 {
6419         R_Textures_Frame();
6420
6421         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6422
6423         r_refdef.farclip = r_farclip_base.value;
6424         if (r_refdef.scene.worldmodel)
6425                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6426         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6427
6428         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6429                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6430         r_refdef.polygonfactor = 0;
6431         r_refdef.polygonoffset = 0;
6432         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6433         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6434
6435         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6436         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6437         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6438         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6439         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6440         if (FAKELIGHT_ENABLED)
6441         {
6442                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6443         }
6444         if (r_showsurfaces.integer)
6445         {
6446                 r_refdef.scene.rtworld = false;
6447                 r_refdef.scene.rtworldshadows = false;
6448                 r_refdef.scene.rtdlight = false;
6449                 r_refdef.scene.rtdlightshadows = false;
6450                 r_refdef.lightmapintensity = 0;
6451         }
6452
6453         if (gamemode == GAME_NEHAHRA)
6454         {
6455                 if (gl_fogenable.integer)
6456                 {
6457                         r_refdef.oldgl_fogenable = true;
6458                         r_refdef.fog_density = gl_fogdensity.value;
6459                         r_refdef.fog_red = gl_fogred.value;
6460                         r_refdef.fog_green = gl_foggreen.value;
6461                         r_refdef.fog_blue = gl_fogblue.value;
6462                         r_refdef.fog_alpha = 1;
6463                         r_refdef.fog_start = 0;
6464                         r_refdef.fog_end = gl_skyclip.value;
6465                         r_refdef.fog_height = 1<<30;
6466                         r_refdef.fog_fadedepth = 128;
6467                 }
6468                 else if (r_refdef.oldgl_fogenable)
6469                 {
6470                         r_refdef.oldgl_fogenable = false;
6471                         r_refdef.fog_density = 0;
6472                         r_refdef.fog_red = 0;
6473                         r_refdef.fog_green = 0;
6474                         r_refdef.fog_blue = 0;
6475                         r_refdef.fog_alpha = 0;
6476                         r_refdef.fog_start = 0;
6477                         r_refdef.fog_end = 0;
6478                         r_refdef.fog_height = 1<<30;
6479                         r_refdef.fog_fadedepth = 128;
6480                 }
6481         }
6482
6483         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6484         r_refdef.fog_start = max(0, r_refdef.fog_start);
6485         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6486
6487         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6488
6489         if (r_refdef.fog_density && r_drawfog.integer)
6490         {
6491                 r_refdef.fogenabled = true;
6492                 // this is the point where the fog reaches 0.9986 alpha, which we
6493                 // consider a good enough cutoff point for the texture
6494                 // (0.9986 * 256 == 255.6)
6495                 if (r_fog_exp2.integer)
6496                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6497                 else
6498                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6499                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6500                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6501                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6502                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6503                         R_BuildFogHeightTexture();
6504                 // fog color was already set
6505                 // update the fog texture
6506                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6507                         R_BuildFogTexture();
6508                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6509                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6510         }
6511         else
6512                 r_refdef.fogenabled = false;
6513
6514         switch(vid.renderpath)
6515         {
6516         case RENDERPATH_GL20:
6517         case RENDERPATH_D3D9:
6518         case RENDERPATH_D3D10:
6519         case RENDERPATH_D3D11:
6520         case RENDERPATH_SOFT:
6521         case RENDERPATH_GLES2:
6522                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6523                 {
6524                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6525                         {
6526                                 // build GLSL gamma texture
6527 #define RAMPWIDTH 256
6528                                 unsigned short ramp[RAMPWIDTH * 3];
6529                                 unsigned char rampbgr[RAMPWIDTH][4];
6530                                 int i;
6531
6532                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6533
6534                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6535                                 for(i = 0; i < RAMPWIDTH; ++i)
6536                                 {
6537                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6538                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6539                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6540                                         rampbgr[i][3] = 0;
6541                                 }
6542                                 if (r_texture_gammaramps)
6543                                 {
6544                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6545                                 }
6546                                 else
6547                                 {
6548                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6549                                 }
6550                         }
6551                 }
6552                 else
6553                 {
6554                         // remove GLSL gamma texture
6555                 }
6556                 break;
6557         case RENDERPATH_GL11:
6558         case RENDERPATH_GL13:
6559         case RENDERPATH_GLES1:
6560                 break;
6561         }
6562 }
6563
6564 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6565 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6566 /*
6567 ================
6568 R_SelectScene
6569 ================
6570 */
6571 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6572         if( scenetype != r_currentscenetype ) {
6573                 // store the old scenetype
6574                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6575                 r_currentscenetype = scenetype;
6576                 // move in the new scene
6577                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6578         }
6579 }
6580
6581 /*
6582 ================
6583 R_GetScenePointer
6584 ================
6585 */
6586 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6587 {
6588         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6589         if( scenetype == r_currentscenetype ) {
6590                 return &r_refdef.scene;
6591         } else {
6592                 return &r_scenes_store[ scenetype ];
6593         }
6594 }
6595
6596 /*
6597 ================
6598 R_RenderView
6599 ================
6600 */
6601 int dpsoftrast_test;
6602 void R_RenderView(void)
6603 {
6604         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6605
6606         dpsoftrast_test = r_test.integer;
6607
6608         if (r_timereport_active)
6609                 R_TimeReport("start");
6610         r_textureframe++; // used only by R_GetCurrentTexture
6611         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6612
6613         if(R_CompileShader_CheckStaticParms())
6614                 R_GLSL_Restart_f();
6615
6616         if (!r_drawentities.integer)
6617                 r_refdef.scene.numentities = 0;
6618
6619         R_AnimCache_ClearCache();
6620         R_FrameData_NewFrame();
6621
6622         /* adjust for stereo display */
6623         if(R_Stereo_Active())
6624         {
6625                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6626                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6627         }
6628
6629         if (r_refdef.view.isoverlay)
6630         {
6631                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6632                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6633                 R_TimeReport("depthclear");
6634
6635                 r_refdef.view.showdebug = false;
6636
6637                 r_waterstate.enabled = false;
6638                 r_waterstate.numwaterplanes = 0;
6639
6640                 R_RenderScene();
6641
6642                 r_refdef.view.matrix = originalmatrix;
6643
6644                 CHECKGLERROR
6645                 return;
6646         }
6647
6648         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6649         {
6650                 r_refdef.view.matrix = originalmatrix;
6651                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6652         }
6653
6654         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6655
6656         R_RenderView_UpdateViewVectors();
6657
6658         R_Shadow_UpdateWorldLightSelection();
6659
6660         R_Bloom_StartFrame();
6661         R_Water_StartFrame();
6662
6663         CHECKGLERROR
6664         if (r_timereport_active)
6665                 R_TimeReport("viewsetup");
6666
6667         R_ResetViewRendering3D();
6668
6669         if (r_refdef.view.clear || r_refdef.fogenabled)
6670         {
6671                 R_ClearScreen(r_refdef.fogenabled);
6672                 if (r_timereport_active)
6673                         R_TimeReport("viewclear");
6674         }
6675         r_refdef.view.clear = true;
6676
6677         // this produces a bloom texture to be used in R_BlendView() later
6678         if (r_bloomstate.hdr)
6679         {
6680                 R_HDR_RenderBloomTexture();
6681                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6682                 r_textureframe++; // used only by R_GetCurrentTexture
6683         }
6684
6685         r_refdef.view.showdebug = true;
6686
6687         R_View_Update();
6688         if (r_timereport_active)
6689                 R_TimeReport("visibility");
6690
6691         r_waterstate.numwaterplanes = 0;
6692         if (r_waterstate.enabled)
6693                 R_RenderWaterPlanes();
6694
6695         R_RenderScene();
6696         r_waterstate.numwaterplanes = 0;
6697
6698         R_BlendView();
6699         if (r_timereport_active)
6700                 R_TimeReport("blendview");
6701
6702         GL_Scissor(0, 0, vid.width, vid.height);
6703         GL_ScissorTest(false);
6704
6705         r_refdef.view.matrix = originalmatrix;
6706
6707         CHECKGLERROR
6708 }
6709
6710 void R_RenderWaterPlanes(void)
6711 {
6712         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6713         {
6714                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6715                 if (r_timereport_active)
6716                         R_TimeReport("waterworld");
6717         }
6718
6719         // don't let sound skip if going slow
6720         if (r_refdef.scene.extraupdate)
6721                 S_ExtraUpdate ();
6722
6723         R_DrawModelsAddWaterPlanes();
6724         if (r_timereport_active)
6725                 R_TimeReport("watermodels");
6726
6727         if (r_waterstate.numwaterplanes)
6728         {
6729                 R_Water_ProcessPlanes();
6730                 if (r_timereport_active)
6731                         R_TimeReport("waterscenes");
6732         }
6733 }
6734
6735 extern void R_DrawLightningBeams (void);
6736 extern void VM_CL_AddPolygonsToMeshQueue (void);
6737 extern void R_DrawPortals (void);
6738 extern cvar_t cl_locs_show;
6739 static void R_DrawLocs(void);
6740 static void R_DrawEntityBBoxes(void);
6741 static void R_DrawModelDecals(void);
6742 extern void R_DrawModelShadows(void);
6743 extern void R_DrawModelShadowMaps(void);
6744 extern cvar_t cl_decals_newsystem;
6745 extern qboolean r_shadow_usingdeferredprepass;
6746 void R_RenderScene(void)
6747 {
6748         qboolean shadowmapping = false;
6749
6750         if (r_timereport_active)
6751                 R_TimeReport("beginscene");
6752
6753         r_refdef.stats.renders++;
6754
6755         R_UpdateFogColor();
6756
6757         // don't let sound skip if going slow
6758         if (r_refdef.scene.extraupdate)
6759                 S_ExtraUpdate ();
6760
6761         R_MeshQueue_BeginScene();
6762
6763         R_SkyStartFrame();
6764
6765         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
6766
6767         if (r_timereport_active)
6768                 R_TimeReport("skystartframe");
6769
6770         if (cl.csqc_vidvars.drawworld)
6771         {
6772                 // don't let sound skip if going slow
6773                 if (r_refdef.scene.extraupdate)
6774                         S_ExtraUpdate ();
6775
6776                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6777                 {
6778                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6779                         if (r_timereport_active)
6780                                 R_TimeReport("worldsky");
6781                 }
6782
6783                 if (R_DrawBrushModelsSky() && r_timereport_active)
6784                         R_TimeReport("bmodelsky");
6785
6786                 if (skyrendermasked && skyrenderlater)
6787                 {
6788                         // we have to force off the water clipping plane while rendering sky
6789                         R_SetupView(false);
6790                         R_Sky();
6791                         R_SetupView(true);
6792                         if (r_timereport_active)
6793                                 R_TimeReport("sky");
6794                 }
6795         }
6796
6797         R_AnimCache_CacheVisibleEntities();
6798         if (r_timereport_active)
6799                 R_TimeReport("animation");
6800
6801         R_Shadow_PrepareLights();
6802         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6803                 R_Shadow_PrepareModelShadows();
6804         if (r_timereport_active)
6805                 R_TimeReport("preparelights");
6806
6807         if (R_Shadow_ShadowMappingEnabled())
6808                 shadowmapping = true;
6809
6810         if (r_shadow_usingdeferredprepass)
6811                 R_Shadow_DrawPrepass();
6812
6813         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6814         {
6815                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6816                 if (r_timereport_active)
6817                         R_TimeReport("worlddepth");
6818         }
6819         if (r_depthfirst.integer >= 2)
6820         {
6821                 R_DrawModelsDepth();
6822                 if (r_timereport_active)
6823                         R_TimeReport("modeldepth");
6824         }
6825
6826         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6827         {
6828                 R_DrawModelShadowMaps();
6829                 R_ResetViewRendering3D();
6830                 // don't let sound skip if going slow
6831                 if (r_refdef.scene.extraupdate)
6832                         S_ExtraUpdate ();
6833         }
6834
6835         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6836         {
6837                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6838                 if (r_timereport_active)
6839                         R_TimeReport("world");
6840         }
6841
6842         // don't let sound skip if going slow
6843         if (r_refdef.scene.extraupdate)
6844                 S_ExtraUpdate ();
6845
6846         R_DrawModels();
6847         if (r_timereport_active)
6848                 R_TimeReport("models");
6849
6850         // don't let sound skip if going slow
6851         if (r_refdef.scene.extraupdate)
6852                 S_ExtraUpdate ();
6853
6854         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6855         {
6856                 R_DrawModelShadows();
6857                 R_ResetViewRendering3D();
6858                 // don't let sound skip if going slow
6859                 if (r_refdef.scene.extraupdate)
6860                         S_ExtraUpdate ();
6861         }
6862
6863         if (!r_shadow_usingdeferredprepass)
6864         {
6865                 R_Shadow_DrawLights();
6866                 if (r_timereport_active)
6867                         R_TimeReport("rtlights");
6868         }
6869
6870         // don't let sound skip if going slow
6871         if (r_refdef.scene.extraupdate)
6872                 S_ExtraUpdate ();
6873
6874         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6875         {
6876                 R_DrawModelShadows();
6877                 R_ResetViewRendering3D();
6878                 // don't let sound skip if going slow
6879                 if (r_refdef.scene.extraupdate)
6880                         S_ExtraUpdate ();
6881         }
6882
6883         if (cl.csqc_vidvars.drawworld)
6884         {
6885                 if (cl_decals_newsystem.integer)
6886                 {
6887                         R_DrawModelDecals();
6888                         if (r_timereport_active)
6889                                 R_TimeReport("modeldecals");
6890                 }
6891                 else
6892                 {
6893                         R_DrawDecals();
6894                         if (r_timereport_active)
6895                                 R_TimeReport("decals");
6896                 }
6897
6898                 R_DrawParticles();
6899                 if (r_timereport_active)
6900                         R_TimeReport("particles");
6901
6902                 R_DrawExplosions();
6903                 if (r_timereport_active)
6904                         R_TimeReport("explosions");
6905
6906                 R_DrawLightningBeams();
6907                 if (r_timereport_active)
6908                         R_TimeReport("lightning");
6909         }
6910
6911         VM_CL_AddPolygonsToMeshQueue();
6912
6913         if (r_refdef.view.showdebug)
6914         {
6915                 if (cl_locs_show.integer)
6916                 {
6917                         R_DrawLocs();
6918                         if (r_timereport_active)
6919                                 R_TimeReport("showlocs");
6920                 }
6921
6922                 if (r_drawportals.integer)
6923                 {
6924                         R_DrawPortals();
6925                         if (r_timereport_active)
6926                                 R_TimeReport("portals");
6927                 }
6928
6929                 if (r_showbboxes.value > 0)
6930                 {
6931                         R_DrawEntityBBoxes();
6932                         if (r_timereport_active)
6933                                 R_TimeReport("bboxes");
6934                 }
6935         }
6936
6937         if (r_transparent.integer)
6938         {
6939                 R_MeshQueue_RenderTransparent();
6940                 if (r_timereport_active)
6941                         R_TimeReport("drawtrans");
6942         }
6943
6944         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
6945         {
6946                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6947                 if (r_timereport_active)
6948                         R_TimeReport("worlddebug");
6949                 R_DrawModelsDebug();
6950                 if (r_timereport_active)
6951                         R_TimeReport("modeldebug");
6952         }
6953
6954         if (cl.csqc_vidvars.drawworld)
6955         {
6956                 R_Shadow_DrawCoronas();
6957                 if (r_timereport_active)
6958                         R_TimeReport("coronas");
6959         }
6960
6961 #if 0
6962         {
6963                 GL_DepthTest(false);
6964                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6965                 GL_Color(1, 1, 1, 1);
6966                 qglBegin(GL_POLYGON);
6967                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6968                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6969                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6970                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6971                 qglEnd();
6972                 qglBegin(GL_POLYGON);
6973                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
6974                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
6975                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
6976                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
6977                 qglEnd();
6978                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6979         }
6980 #endif
6981
6982         // don't let sound skip if going slow
6983         if (r_refdef.scene.extraupdate)
6984                 S_ExtraUpdate ();
6985
6986         R_ResetViewRendering2D();
6987 }
6988
6989 static const unsigned short bboxelements[36] =
6990 {
6991         5, 1, 3, 5, 3, 7,
6992         6, 2, 0, 6, 0, 4,
6993         7, 3, 2, 7, 2, 6,
6994         4, 0, 1, 4, 1, 5,
6995         4, 5, 7, 4, 7, 6,
6996         1, 0, 2, 1, 2, 3,
6997 };
6998
6999 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7000 {
7001         int i;
7002         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7003
7004         RSurf_ActiveWorldEntity();
7005
7006         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7007         GL_DepthMask(false);
7008         GL_DepthRange(0, 1);
7009         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7010 //      R_Mesh_ResetTextureState();
7011
7012         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7013         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7014         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7015         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7016         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7017         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7018         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7019         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7020         R_FillColors(color4f, 8, cr, cg, cb, ca);
7021         if (r_refdef.fogenabled)
7022         {
7023                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7024                 {
7025                         f1 = RSurf_FogVertex(v);
7026                         f2 = 1 - f1;
7027                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7028                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7029                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7030                 }
7031         }
7032         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7033         R_Mesh_ResetTextureState();
7034         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7035         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7036 }
7037
7038 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7039 {
7040         int i;
7041         float color[4];
7042         prvm_edict_t *edict;
7043         prvm_prog_t *prog_save = prog;
7044
7045         // this function draws bounding boxes of server entities
7046         if (!sv.active)
7047                 return;
7048
7049         GL_CullFace(GL_NONE);
7050         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7051
7052         prog = 0;
7053         SV_VM_Begin();
7054         for (i = 0;i < numsurfaces;i++)
7055         {
7056                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7057                 switch ((int)edict->fields.server->solid)
7058                 {
7059                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7060                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7061                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7062                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7063                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7064                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7065                 }
7066                 color[3] *= r_showbboxes.value;
7067                 color[3] = bound(0, color[3], 1);
7068                 GL_DepthTest(!r_showdisabledepthtest.integer);
7069                 GL_CullFace(r_refdef.view.cullface_front);
7070                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7071         }
7072         SV_VM_End();
7073         prog = prog_save;
7074 }
7075
7076 static void R_DrawEntityBBoxes(void)
7077 {
7078         int i;
7079         prvm_edict_t *edict;
7080         vec3_t center;
7081         prvm_prog_t *prog_save = prog;
7082
7083         // this function draws bounding boxes of server entities
7084         if (!sv.active)
7085                 return;
7086
7087         prog = 0;
7088         SV_VM_Begin();
7089         for (i = 0;i < prog->num_edicts;i++)
7090         {
7091                 edict = PRVM_EDICT_NUM(i);
7092                 if (edict->priv.server->free)
7093                         continue;
7094                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7095                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7096                         continue;
7097                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7098                         continue;
7099                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7100                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7101         }
7102         SV_VM_End();
7103         prog = prog_save;
7104 }
7105
7106 static const int nomodelelement3i[24] =
7107 {
7108         5, 2, 0,
7109         5, 1, 2,
7110         5, 0, 3,
7111         5, 3, 1,
7112         0, 2, 4,
7113         2, 1, 4,
7114         3, 0, 4,
7115         1, 3, 4
7116 };
7117
7118 static const unsigned short nomodelelement3s[24] =
7119 {
7120         5, 2, 0,
7121         5, 1, 2,
7122         5, 0, 3,
7123         5, 3, 1,
7124         0, 2, 4,
7125         2, 1, 4,
7126         3, 0, 4,
7127         1, 3, 4
7128 };
7129
7130 static const float nomodelvertex3f[6*3] =
7131 {
7132         -16,   0,   0,
7133          16,   0,   0,
7134           0, -16,   0,
7135           0,  16,   0,
7136           0,   0, -16,
7137           0,   0,  16
7138 };
7139
7140 static const float nomodelcolor4f[6*4] =
7141 {
7142         0.0f, 0.0f, 0.5f, 1.0f,
7143         0.0f, 0.0f, 0.5f, 1.0f,
7144         0.0f, 0.5f, 0.0f, 1.0f,
7145         0.0f, 0.5f, 0.0f, 1.0f,
7146         0.5f, 0.0f, 0.0f, 1.0f,
7147         0.5f, 0.0f, 0.0f, 1.0f
7148 };
7149
7150 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7151 {
7152         int i;
7153         float f1, f2, *c;
7154         float color4f[6*4];
7155
7156         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7157
7158         // this is only called once per entity so numsurfaces is always 1, and
7159         // surfacelist is always {0}, so this code does not handle batches
7160
7161         if (rsurface.ent_flags & RENDER_ADDITIVE)
7162         {
7163                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7164                 GL_DepthMask(false);
7165         }
7166         else if (rsurface.colormod[3] < 1)
7167         {
7168                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7169                 GL_DepthMask(false);
7170         }
7171         else
7172         {
7173                 GL_BlendFunc(GL_ONE, GL_ZERO);
7174                 GL_DepthMask(true);
7175         }
7176         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7177         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7178         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7179         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7180         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7181         for (i = 0, c = color4f;i < 6;i++, c += 4)
7182         {
7183                 c[0] *= rsurface.colormod[0];
7184                 c[1] *= rsurface.colormod[1];
7185                 c[2] *= rsurface.colormod[2];
7186                 c[3] *= rsurface.colormod[3];
7187         }
7188         if (r_refdef.fogenabled)
7189         {
7190                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7191                 {
7192                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7193                         f2 = 1 - f1;
7194                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7195                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7196                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7197                 }
7198         }
7199 //      R_Mesh_ResetTextureState();
7200         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7201         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7202         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7203 }
7204
7205 void R_DrawNoModel(entity_render_t *ent)
7206 {
7207         vec3_t org;
7208         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7209         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7210                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7211         else
7212                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7213 }
7214
7215 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7216 {
7217         vec3_t right1, right2, diff, normal;
7218
7219         VectorSubtract (org2, org1, normal);
7220
7221         // calculate 'right' vector for start
7222         VectorSubtract (r_refdef.view.origin, org1, diff);
7223         CrossProduct (normal, diff, right1);
7224         VectorNormalize (right1);
7225
7226         // calculate 'right' vector for end
7227         VectorSubtract (r_refdef.view.origin, org2, diff);
7228         CrossProduct (normal, diff, right2);
7229         VectorNormalize (right2);
7230
7231         vert[ 0] = org1[0] + width * right1[0];
7232         vert[ 1] = org1[1] + width * right1[1];
7233         vert[ 2] = org1[2] + width * right1[2];
7234         vert[ 3] = org1[0] - width * right1[0];
7235         vert[ 4] = org1[1] - width * right1[1];
7236         vert[ 5] = org1[2] - width * right1[2];
7237         vert[ 6] = org2[0] - width * right2[0];
7238         vert[ 7] = org2[1] - width * right2[1];
7239         vert[ 8] = org2[2] - width * right2[2];
7240         vert[ 9] = org2[0] + width * right2[0];
7241         vert[10] = org2[1] + width * right2[1];
7242         vert[11] = org2[2] + width * right2[2];
7243 }
7244
7245 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7246 {
7247         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7248         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7249         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7250         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7251         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7252         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7253         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7254         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7255         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7256         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7257         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7258         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7259 }
7260
7261 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7262 {
7263         int i;
7264         float *vertex3f;
7265         float v[3];
7266         VectorSet(v, x, y, z);
7267         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7268                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7269                         break;
7270         if (i == mesh->numvertices)
7271         {
7272                 if (mesh->numvertices < mesh->maxvertices)
7273                 {
7274                         VectorCopy(v, vertex3f);
7275                         mesh->numvertices++;
7276                 }
7277                 return mesh->numvertices;
7278         }
7279         else
7280                 return i;
7281 }
7282
7283 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7284 {
7285         int i;
7286         int *e, element[3];
7287         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7288         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7289         e = mesh->element3i + mesh->numtriangles * 3;
7290         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7291         {
7292                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7293                 if (mesh->numtriangles < mesh->maxtriangles)
7294                 {
7295                         *e++ = element[0];
7296                         *e++ = element[1];
7297                         *e++ = element[2];
7298                         mesh->numtriangles++;
7299                 }
7300                 element[1] = element[2];
7301         }
7302 }
7303
7304 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7305 {
7306         int i;
7307         int *e, element[3];
7308         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7309         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7310         e = mesh->element3i + mesh->numtriangles * 3;
7311         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7312         {
7313                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7314                 if (mesh->numtriangles < mesh->maxtriangles)
7315                 {
7316                         *e++ = element[0];
7317                         *e++ = element[1];
7318                         *e++ = element[2];
7319                         mesh->numtriangles++;
7320                 }
7321                 element[1] = element[2];
7322         }
7323 }
7324
7325 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7326 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7327 {
7328         int planenum, planenum2;
7329         int w;
7330         int tempnumpoints;
7331         mplane_t *plane, *plane2;
7332         double maxdist;
7333         double temppoints[2][256*3];
7334         // figure out how large a bounding box we need to properly compute this brush
7335         maxdist = 0;
7336         for (w = 0;w < numplanes;w++)
7337                 maxdist = max(maxdist, fabs(planes[w].dist));
7338         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7339         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7340         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7341         {
7342                 w = 0;
7343                 tempnumpoints = 4;
7344                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7345                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7346                 {
7347                         if (planenum2 == planenum)
7348                                 continue;
7349                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7350                         w = !w;
7351                 }
7352                 if (tempnumpoints < 3)
7353                         continue;
7354                 // generate elements forming a triangle fan for this polygon
7355                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7356         }
7357 }
7358
7359 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7360 {
7361         texturelayer_t *layer;
7362         layer = t->currentlayers + t->currentnumlayers++;
7363         layer->type = type;
7364         layer->depthmask = depthmask;
7365         layer->blendfunc1 = blendfunc1;
7366         layer->blendfunc2 = blendfunc2;
7367         layer->texture = texture;
7368         layer->texmatrix = *matrix;
7369         layer->color[0] = r;
7370         layer->color[1] = g;
7371         layer->color[2] = b;
7372         layer->color[3] = a;
7373 }
7374
7375 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7376 {
7377         if(parms[0] == 0 && parms[1] == 0)
7378                 return false;
7379         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7380                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7381                         return false;
7382         return true;
7383 }
7384
7385 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7386 {
7387         double index, f;
7388         index = parms[2] + rsurface.shadertime * parms[3];
7389         index -= floor(index);
7390         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7391         {
7392         default:
7393         case Q3WAVEFUNC_NONE:
7394         case Q3WAVEFUNC_NOISE:
7395         case Q3WAVEFUNC_COUNT:
7396                 f = 0;
7397                 break;
7398         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7399         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7400         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7401         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7402         case Q3WAVEFUNC_TRIANGLE:
7403                 index *= 4;
7404                 f = index - floor(index);
7405                 if (index < 1)
7406                         f = f;
7407                 else if (index < 2)
7408                         f = 1 - f;
7409                 else if (index < 3)
7410                         f = -f;
7411                 else
7412                         f = -(1 - f);
7413                 break;
7414         }
7415         f = parms[0] + parms[1] * f;
7416         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7417                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7418         return (float) f;
7419 }
7420
7421 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7422 {
7423         int w, h, idx;
7424         double f;
7425         double offsetd[2];
7426         float tcmat[12];
7427         matrix4x4_t matrix, temp;
7428         switch(tcmod->tcmod)
7429         {
7430                 case Q3TCMOD_COUNT:
7431                 case Q3TCMOD_NONE:
7432                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7433                                 matrix = r_waterscrollmatrix;
7434                         else
7435                                 matrix = identitymatrix;
7436                         break;
7437                 case Q3TCMOD_ENTITYTRANSLATE:
7438                         // this is used in Q3 to allow the gamecode to control texcoord
7439                         // scrolling on the entity, which is not supported in darkplaces yet.
7440                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7441                         break;
7442                 case Q3TCMOD_ROTATE:
7443                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7444                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7445                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7446                         break;
7447                 case Q3TCMOD_SCALE:
7448                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7449                         break;
7450                 case Q3TCMOD_SCROLL:
7451                         // extra care is needed because of precision breakdown with large values of time
7452                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7453                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7454                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7455                         break;
7456                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7457                         w = (int) tcmod->parms[0];
7458                         h = (int) tcmod->parms[1];
7459                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7460                         f = f - floor(f);
7461                         idx = (int) floor(f * w * h);
7462                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7463                         break;
7464                 case Q3TCMOD_STRETCH:
7465                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7466                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7467                         break;
7468                 case Q3TCMOD_TRANSFORM:
7469                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7470                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7471                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7472                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7473                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7474                         break;
7475                 case Q3TCMOD_TURBULENT:
7476                         // this is handled in the RSurf_PrepareVertices function
7477                         matrix = identitymatrix;
7478                         break;
7479         }
7480         temp = *texmatrix;
7481         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7482 }
7483
7484 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7485 {
7486         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7487         char name[MAX_QPATH];
7488         skinframe_t *skinframe;
7489         unsigned char pixels[296*194];
7490         strlcpy(cache->name, skinname, sizeof(cache->name));
7491         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7492         if (developer_loading.integer)
7493                 Con_Printf("loading %s\n", name);
7494         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7495         if (!skinframe || !skinframe->base)
7496         {
7497                 unsigned char *f;
7498                 fs_offset_t filesize;
7499                 skinframe = NULL;
7500                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7501                 if (f)
7502                 {
7503                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7504                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7505                         Mem_Free(f);
7506                 }
7507         }
7508         cache->skinframe = skinframe;
7509 }
7510
7511 texture_t *R_GetCurrentTexture(texture_t *t)
7512 {
7513         int i;
7514         const entity_render_t *ent = rsurface.entity;
7515         dp_model_t *model = ent->model;
7516         q3shaderinfo_layer_tcmod_t *tcmod;
7517
7518         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7519                 return t->currentframe;
7520         t->update_lastrenderframe = r_textureframe;
7521         t->update_lastrenderentity = (void *)ent;
7522
7523         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7524                 t->camera_entity = ent->entitynumber;
7525         else
7526                 t->camera_entity = 0;
7527
7528         // switch to an alternate material if this is a q1bsp animated material
7529         {
7530                 texture_t *texture = t;
7531                 int s = rsurface.ent_skinnum;
7532                 if ((unsigned int)s >= (unsigned int)model->numskins)
7533                         s = 0;
7534                 if (model->skinscenes)
7535                 {
7536                         if (model->skinscenes[s].framecount > 1)
7537                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7538                         else
7539                                 s = model->skinscenes[s].firstframe;
7540                 }
7541                 if (s > 0)
7542                         t = t + s * model->num_surfaces;
7543                 if (t->animated)
7544                 {
7545                         // use an alternate animation if the entity's frame is not 0,
7546                         // and only if the texture has an alternate animation
7547                         if (rsurface.ent_alttextures && t->anim_total[1])
7548                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7549                         else
7550                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7551                 }
7552                 texture->currentframe = t;
7553         }
7554
7555         // update currentskinframe to be a qw skin or animation frame
7556         if (rsurface.ent_qwskin >= 0)
7557         {
7558                 i = rsurface.ent_qwskin;
7559                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7560                 {
7561                         r_qwskincache_size = cl.maxclients;
7562                         if (r_qwskincache)
7563                                 Mem_Free(r_qwskincache);
7564                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7565                 }
7566                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7567                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7568                 t->currentskinframe = r_qwskincache[i].skinframe;
7569                 if (t->currentskinframe == NULL)
7570                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7571         }
7572         else if (t->numskinframes >= 2)
7573                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7574         if (t->backgroundnumskinframes >= 2)
7575                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7576
7577         t->currentmaterialflags = t->basematerialflags;
7578         t->currentalpha = rsurface.colormod[3];
7579         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7580                 t->currentalpha *= r_wateralpha.value;
7581         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7582                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7583         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7584                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7585         if (!(rsurface.ent_flags & RENDER_LIGHT))
7586                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7587         else if (FAKELIGHT_ENABLED)
7588         {
7589                 // no modellight if using fakelight for the map
7590         }
7591         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7592         {
7593                 // pick a model lighting mode
7594                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7595                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7596                 else
7597                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7598         }
7599         if (rsurface.ent_flags & RENDER_ADDITIVE)
7600                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7601         else if (t->currentalpha < 1)
7602                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7603         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7604                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7605         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7606                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7607         if (t->backgroundnumskinframes)
7608                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7609         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7610         {
7611                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7612                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7613         }
7614         else
7615                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7616         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7617                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7618
7619         // there is no tcmod
7620         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7621         {
7622                 t->currenttexmatrix = r_waterscrollmatrix;
7623                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7624         }
7625         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7626         {
7627                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7628                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7629         }
7630
7631         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7632                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7633         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7634                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7635
7636         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7637         if (t->currentskinframe->qpixels)
7638                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7639         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7640         if (!t->basetexture)
7641                 t->basetexture = r_texture_notexture;
7642         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7643         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7644         t->nmaptexture = t->currentskinframe->nmap;
7645         if (!t->nmaptexture)
7646                 t->nmaptexture = r_texture_blanknormalmap;
7647         t->glosstexture = r_texture_black;
7648         t->glowtexture = t->currentskinframe->glow;
7649         t->fogtexture = t->currentskinframe->fog;
7650         t->reflectmasktexture = t->currentskinframe->reflect;
7651         if (t->backgroundnumskinframes)
7652         {
7653                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7654                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7655                 t->backgroundglosstexture = r_texture_black;
7656                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7657                 if (!t->backgroundnmaptexture)
7658                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7659         }
7660         else
7661         {
7662                 t->backgroundbasetexture = r_texture_white;
7663                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7664                 t->backgroundglosstexture = r_texture_black;
7665                 t->backgroundglowtexture = NULL;
7666         }
7667         t->specularpower = r_shadow_glossexponent.value;
7668         // TODO: store reference values for these in the texture?
7669         t->specularscale = 0;
7670         if (r_shadow_gloss.integer > 0)
7671         {
7672                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7673                 {
7674                         if (r_shadow_glossintensity.value > 0)
7675                         {
7676                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7677                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7678                                 t->specularscale = r_shadow_glossintensity.value;
7679                         }
7680                 }
7681                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7682                 {
7683                         t->glosstexture = r_texture_white;
7684                         t->backgroundglosstexture = r_texture_white;
7685                         t->specularscale = r_shadow_gloss2intensity.value;
7686                         t->specularpower = r_shadow_gloss2exponent.value;
7687                 }
7688         }
7689         t->specularscale *= t->specularscalemod;
7690         t->specularpower *= t->specularpowermod;
7691
7692         // lightmaps mode looks bad with dlights using actual texturing, so turn
7693         // off the colormap and glossmap, but leave the normalmap on as it still
7694         // accurately represents the shading involved
7695         if (gl_lightmaps.integer)
7696         {
7697                 t->basetexture = r_texture_grey128;
7698                 t->pantstexture = r_texture_black;
7699                 t->shirttexture = r_texture_black;
7700                 t->nmaptexture = r_texture_blanknormalmap;
7701                 t->glosstexture = r_texture_black;
7702                 t->glowtexture = NULL;
7703                 t->fogtexture = NULL;
7704                 t->reflectmasktexture = NULL;
7705                 t->backgroundbasetexture = NULL;
7706                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7707                 t->backgroundglosstexture = r_texture_black;
7708                 t->backgroundglowtexture = NULL;
7709                 t->specularscale = 0;
7710                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7711         }
7712
7713         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7714         VectorClear(t->dlightcolor);
7715         t->currentnumlayers = 0;
7716         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7717         {
7718                 int blendfunc1, blendfunc2;
7719                 qboolean depthmask;
7720                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7721                 {
7722                         blendfunc1 = GL_SRC_ALPHA;
7723                         blendfunc2 = GL_ONE;
7724                 }
7725                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7726                 {
7727                         blendfunc1 = GL_SRC_ALPHA;
7728                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7729                 }
7730                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7731                 {
7732                         blendfunc1 = t->customblendfunc[0];
7733                         blendfunc2 = t->customblendfunc[1];
7734                 }
7735                 else
7736                 {
7737                         blendfunc1 = GL_ONE;
7738                         blendfunc2 = GL_ZERO;
7739                 }
7740                 // don't colormod evilblend textures
7741                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7742                         VectorSet(t->lightmapcolor, 1, 1, 1);
7743                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7744                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7745                 {
7746                         // fullbright is not affected by r_refdef.lightmapintensity
7747                         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]);
7748                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7749                                 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]);
7750                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7751                                 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]);
7752                 }
7753                 else
7754                 {
7755                         vec3_t ambientcolor;
7756                         float colorscale;
7757                         // set the color tint used for lights affecting this surface
7758                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7759                         colorscale = 2;
7760                         // q3bsp has no lightmap updates, so the lightstylevalue that
7761                         // would normally be baked into the lightmap must be
7762                         // applied to the color
7763                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7764                         if (model->type == mod_brushq3)
7765                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7766                         colorscale *= r_refdef.lightmapintensity;
7767                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7768                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7769                         // basic lit geometry
7770                         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]);
7771                         // add pants/shirt if needed
7772                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7773                                 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]);
7774                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7775                                 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]);
7776                         // now add ambient passes if needed
7777                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7778                         {
7779                                 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]);
7780                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7781                                         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]);
7782                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7783                                         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]);
7784                         }
7785                 }
7786                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7787                         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]);
7788                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7789                 {
7790                         // if this is opaque use alpha blend which will darken the earlier
7791                         // passes cheaply.
7792                         //
7793                         // if this is an alpha blended material, all the earlier passes
7794                         // were darkened by fog already, so we only need to add the fog
7795                         // color ontop through the fog mask texture
7796                         //
7797                         // if this is an additive blended material, all the earlier passes
7798                         // were darkened by fog already, and we should not add fog color
7799                         // (because the background was not darkened, there is no fog color
7800                         // that was lost behind it).
7801                         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]);
7802                 }
7803         }
7804
7805         return t->currentframe;
7806 }
7807
7808 rsurfacestate_t rsurface;
7809
7810 void RSurf_ActiveWorldEntity(void)
7811 {
7812         dp_model_t *model = r_refdef.scene.worldmodel;
7813         //if (rsurface.entity == r_refdef.scene.worldentity)
7814         //      return;
7815         rsurface.entity = r_refdef.scene.worldentity;
7816         rsurface.skeleton = NULL;
7817         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7818         rsurface.ent_skinnum = 0;
7819         rsurface.ent_qwskin = -1;
7820         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7821         rsurface.shadertime = r_refdef.scene.time;
7822         rsurface.matrix = identitymatrix;
7823         rsurface.inversematrix = identitymatrix;
7824         rsurface.matrixscale = 1;
7825         rsurface.inversematrixscale = 1;
7826         R_EntityMatrix(&identitymatrix);
7827         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7828         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7829         rsurface.fograngerecip = r_refdef.fograngerecip;
7830         rsurface.fogheightfade = r_refdef.fogheightfade;
7831         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7832         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7833         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7834         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7835         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7836         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7837         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7838         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7839         rsurface.colormod[3] = 1;
7840         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);
7841         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7842         rsurface.frameblend[0].lerp = 1;
7843         rsurface.ent_alttextures = false;
7844         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7845         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7846         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7847         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7848         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7849         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7850         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7851         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7852         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7853         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7854         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7855         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7856         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7857         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7858         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7859         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7860         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7861         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7862         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7863         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7864         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7865         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7866         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7867         rsurface.modelelement3i = model->surfmesh.data_element3i;
7868         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7869         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7870         rsurface.modelelement3s = model->surfmesh.data_element3s;
7871         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7872         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7873         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7874         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7875         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7876         rsurface.modelsurfaces = model->data_surfaces;
7877         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7878         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7879         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7880         rsurface.modelgeneratedvertex = false;
7881         rsurface.batchgeneratedvertex = false;
7882         rsurface.batchfirstvertex = 0;
7883         rsurface.batchnumvertices = 0;
7884         rsurface.batchfirsttriangle = 0;
7885         rsurface.batchnumtriangles = 0;
7886         rsurface.batchvertex3f  = NULL;
7887         rsurface.batchvertex3f_vertexbuffer = NULL;
7888         rsurface.batchvertex3f_bufferoffset = 0;
7889         rsurface.batchsvector3f = NULL;
7890         rsurface.batchsvector3f_vertexbuffer = NULL;
7891         rsurface.batchsvector3f_bufferoffset = 0;
7892         rsurface.batchtvector3f = NULL;
7893         rsurface.batchtvector3f_vertexbuffer = NULL;
7894         rsurface.batchtvector3f_bufferoffset = 0;
7895         rsurface.batchnormal3f  = NULL;
7896         rsurface.batchnormal3f_vertexbuffer = NULL;
7897         rsurface.batchnormal3f_bufferoffset = 0;
7898         rsurface.batchlightmapcolor4f = NULL;
7899         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7900         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7901         rsurface.batchtexcoordtexture2f = NULL;
7902         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7903         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7904         rsurface.batchtexcoordlightmap2f = NULL;
7905         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7906         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7907         rsurface.batchvertexmesh = NULL;
7908         rsurface.batchvertexmeshbuffer = NULL;
7909         rsurface.batchvertex3fbuffer = NULL;
7910         rsurface.batchelement3i = NULL;
7911         rsurface.batchelement3i_indexbuffer = NULL;
7912         rsurface.batchelement3i_bufferoffset = 0;
7913         rsurface.batchelement3s = NULL;
7914         rsurface.batchelement3s_indexbuffer = NULL;
7915         rsurface.batchelement3s_bufferoffset = 0;
7916         rsurface.passcolor4f = NULL;
7917         rsurface.passcolor4f_vertexbuffer = NULL;
7918         rsurface.passcolor4f_bufferoffset = 0;
7919 }
7920
7921 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7922 {
7923         dp_model_t *model = ent->model;
7924         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7925         //      return;
7926         rsurface.entity = (entity_render_t *)ent;
7927         rsurface.skeleton = ent->skeleton;
7928         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7929         rsurface.ent_skinnum = ent->skinnum;
7930         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;
7931         rsurface.ent_flags = ent->flags;
7932         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
7933         rsurface.matrix = ent->matrix;
7934         rsurface.inversematrix = ent->inversematrix;
7935         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7936         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7937         R_EntityMatrix(&rsurface.matrix);
7938         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7939         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7940         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7941         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7942         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7943         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7944         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7945         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7946         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7947         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7948         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7949         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7950         rsurface.colormod[3] = ent->alpha;
7951         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7952         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7953         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7954         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7955         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7956         if (ent->model->brush.submodel && !prepass)
7957         {
7958                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7959                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7960         }
7961         if (model->surfmesh.isanimated && model->AnimateVertices)
7962         {
7963                 if (ent->animcache_vertex3f)
7964                 {
7965                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7966                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7967                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7968                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7969                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7970                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7971                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7972                 }
7973                 else if (wanttangents)
7974                 {
7975                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7976                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7977                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7978                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7979                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7980                         rsurface.modelvertexmesh = NULL;
7981                         rsurface.modelvertexmeshbuffer = NULL;
7982                         rsurface.modelvertex3fbuffer = NULL;
7983                 }
7984                 else if (wantnormals)
7985                 {
7986                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7987                         rsurface.modelsvector3f = NULL;
7988                         rsurface.modeltvector3f = NULL;
7989                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7990                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7991                         rsurface.modelvertexmesh = NULL;
7992                         rsurface.modelvertexmeshbuffer = NULL;
7993                         rsurface.modelvertex3fbuffer = NULL;
7994                 }
7995                 else
7996                 {
7997                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7998                         rsurface.modelsvector3f = NULL;
7999                         rsurface.modeltvector3f = NULL;
8000                         rsurface.modelnormal3f = NULL;
8001                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8002                         rsurface.modelvertexmesh = NULL;
8003                         rsurface.modelvertexmeshbuffer = NULL;
8004                         rsurface.modelvertex3fbuffer = NULL;
8005                 }
8006                 rsurface.modelvertex3f_vertexbuffer = 0;
8007                 rsurface.modelvertex3f_bufferoffset = 0;
8008                 rsurface.modelsvector3f_vertexbuffer = 0;
8009                 rsurface.modelsvector3f_bufferoffset = 0;
8010                 rsurface.modeltvector3f_vertexbuffer = 0;
8011                 rsurface.modeltvector3f_bufferoffset = 0;
8012                 rsurface.modelnormal3f_vertexbuffer = 0;
8013                 rsurface.modelnormal3f_bufferoffset = 0;
8014                 rsurface.modelgeneratedvertex = true;
8015         }
8016         else
8017         {
8018                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8019                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8020                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8021                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8022                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8023                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8024                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8025                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8026                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8027                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8028                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8029                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8030                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8031                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8032                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8033                 rsurface.modelgeneratedvertex = false;
8034         }
8035         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8036         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8037         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8038         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8039         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8040         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8041         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8042         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8043         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8044         rsurface.modelelement3i = model->surfmesh.data_element3i;
8045         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8046         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8047         rsurface.modelelement3s = model->surfmesh.data_element3s;
8048         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8049         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8050         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8051         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8052         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8053         rsurface.modelsurfaces = model->data_surfaces;
8054         rsurface.batchgeneratedvertex = false;
8055         rsurface.batchfirstvertex = 0;
8056         rsurface.batchnumvertices = 0;
8057         rsurface.batchfirsttriangle = 0;
8058         rsurface.batchnumtriangles = 0;
8059         rsurface.batchvertex3f  = NULL;
8060         rsurface.batchvertex3f_vertexbuffer = NULL;
8061         rsurface.batchvertex3f_bufferoffset = 0;
8062         rsurface.batchsvector3f = NULL;
8063         rsurface.batchsvector3f_vertexbuffer = NULL;
8064         rsurface.batchsvector3f_bufferoffset = 0;
8065         rsurface.batchtvector3f = NULL;
8066         rsurface.batchtvector3f_vertexbuffer = NULL;
8067         rsurface.batchtvector3f_bufferoffset = 0;
8068         rsurface.batchnormal3f  = NULL;
8069         rsurface.batchnormal3f_vertexbuffer = NULL;
8070         rsurface.batchnormal3f_bufferoffset = 0;
8071         rsurface.batchlightmapcolor4f = NULL;
8072         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8073         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8074         rsurface.batchtexcoordtexture2f = NULL;
8075         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8076         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8077         rsurface.batchtexcoordlightmap2f = NULL;
8078         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8079         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8080         rsurface.batchvertexmesh = NULL;
8081         rsurface.batchvertexmeshbuffer = NULL;
8082         rsurface.batchvertex3fbuffer = NULL;
8083         rsurface.batchelement3i = NULL;
8084         rsurface.batchelement3i_indexbuffer = NULL;
8085         rsurface.batchelement3i_bufferoffset = 0;
8086         rsurface.batchelement3s = NULL;
8087         rsurface.batchelement3s_indexbuffer = NULL;
8088         rsurface.batchelement3s_bufferoffset = 0;
8089         rsurface.passcolor4f = NULL;
8090         rsurface.passcolor4f_vertexbuffer = NULL;
8091         rsurface.passcolor4f_bufferoffset = 0;
8092 }
8093
8094 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)
8095 {
8096         rsurface.entity = r_refdef.scene.worldentity;
8097         rsurface.skeleton = NULL;
8098         rsurface.ent_skinnum = 0;
8099         rsurface.ent_qwskin = -1;
8100         rsurface.ent_flags = entflags;
8101         rsurface.shadertime = r_refdef.scene.time - shadertime;
8102         rsurface.modelnumvertices = numvertices;
8103         rsurface.modelnumtriangles = numtriangles;
8104         rsurface.matrix = *matrix;
8105         rsurface.inversematrix = *inversematrix;
8106         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8107         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8108         R_EntityMatrix(&rsurface.matrix);
8109         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8110         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8111         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8112         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8113         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8114         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8115         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8116         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8117         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8118         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8119         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8120         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8121         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);
8122         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8123         rsurface.frameblend[0].lerp = 1;
8124         rsurface.ent_alttextures = false;
8125         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8126         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8127         if (wanttangents)
8128         {
8129                 rsurface.modelvertex3f = (float *)vertex3f;
8130                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8131                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8132                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8133         }
8134         else if (wantnormals)
8135         {
8136                 rsurface.modelvertex3f = (float *)vertex3f;
8137                 rsurface.modelsvector3f = NULL;
8138                 rsurface.modeltvector3f = NULL;
8139                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8140         }
8141         else
8142         {
8143                 rsurface.modelvertex3f = (float *)vertex3f;
8144                 rsurface.modelsvector3f = NULL;
8145                 rsurface.modeltvector3f = NULL;
8146                 rsurface.modelnormal3f = NULL;
8147         }
8148         rsurface.modelvertexmesh = NULL;
8149         rsurface.modelvertexmeshbuffer = NULL;
8150         rsurface.modelvertex3fbuffer = NULL;
8151         rsurface.modelvertex3f_vertexbuffer = 0;
8152         rsurface.modelvertex3f_bufferoffset = 0;
8153         rsurface.modelsvector3f_vertexbuffer = 0;
8154         rsurface.modelsvector3f_bufferoffset = 0;
8155         rsurface.modeltvector3f_vertexbuffer = 0;
8156         rsurface.modeltvector3f_bufferoffset = 0;
8157         rsurface.modelnormal3f_vertexbuffer = 0;
8158         rsurface.modelnormal3f_bufferoffset = 0;
8159         rsurface.modelgeneratedvertex = true;
8160         rsurface.modellightmapcolor4f  = (float *)color4f;
8161         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8162         rsurface.modellightmapcolor4f_bufferoffset = 0;
8163         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8164         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8165         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8166         rsurface.modeltexcoordlightmap2f  = NULL;
8167         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8168         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8169         rsurface.modelelement3i = (int *)element3i;
8170         rsurface.modelelement3i_indexbuffer = NULL;
8171         rsurface.modelelement3i_bufferoffset = 0;
8172         rsurface.modelelement3s = (unsigned short *)element3s;
8173         rsurface.modelelement3s_indexbuffer = NULL;
8174         rsurface.modelelement3s_bufferoffset = 0;
8175         rsurface.modellightmapoffsets = NULL;
8176         rsurface.modelsurfaces = NULL;
8177         rsurface.batchgeneratedvertex = false;
8178         rsurface.batchfirstvertex = 0;
8179         rsurface.batchnumvertices = 0;
8180         rsurface.batchfirsttriangle = 0;
8181         rsurface.batchnumtriangles = 0;
8182         rsurface.batchvertex3f  = NULL;
8183         rsurface.batchvertex3f_vertexbuffer = NULL;
8184         rsurface.batchvertex3f_bufferoffset = 0;
8185         rsurface.batchsvector3f = NULL;
8186         rsurface.batchsvector3f_vertexbuffer = NULL;
8187         rsurface.batchsvector3f_bufferoffset = 0;
8188         rsurface.batchtvector3f = NULL;
8189         rsurface.batchtvector3f_vertexbuffer = NULL;
8190         rsurface.batchtvector3f_bufferoffset = 0;
8191         rsurface.batchnormal3f  = NULL;
8192         rsurface.batchnormal3f_vertexbuffer = NULL;
8193         rsurface.batchnormal3f_bufferoffset = 0;
8194         rsurface.batchlightmapcolor4f = NULL;
8195         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8196         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8197         rsurface.batchtexcoordtexture2f = NULL;
8198         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8199         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8200         rsurface.batchtexcoordlightmap2f = NULL;
8201         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8202         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8203         rsurface.batchvertexmesh = NULL;
8204         rsurface.batchvertexmeshbuffer = NULL;
8205         rsurface.batchvertex3fbuffer = NULL;
8206         rsurface.batchelement3i = NULL;
8207         rsurface.batchelement3i_indexbuffer = NULL;
8208         rsurface.batchelement3i_bufferoffset = 0;
8209         rsurface.batchelement3s = NULL;
8210         rsurface.batchelement3s_indexbuffer = NULL;
8211         rsurface.batchelement3s_bufferoffset = 0;
8212         rsurface.passcolor4f = NULL;
8213         rsurface.passcolor4f_vertexbuffer = NULL;
8214         rsurface.passcolor4f_bufferoffset = 0;
8215
8216         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8217         {
8218                 if ((wantnormals || wanttangents) && !normal3f)
8219                 {
8220                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8221                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8222                 }
8223                 if (wanttangents && !svector3f)
8224                 {
8225                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8226                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8227                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8228                 }
8229         }
8230 }
8231
8232 float RSurf_FogPoint(const float *v)
8233 {
8234         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8235         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8236         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8237         float FogHeightFade = r_refdef.fogheightfade;
8238         float fogfrac;
8239         unsigned int fogmasktableindex;
8240         if (r_refdef.fogplaneviewabove)
8241                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8242         else
8243                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8244         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8245         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8246 }
8247
8248 float RSurf_FogVertex(const float *v)
8249 {
8250         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8251         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8252         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8253         float FogHeightFade = rsurface.fogheightfade;
8254         float fogfrac;
8255         unsigned int fogmasktableindex;
8256         if (r_refdef.fogplaneviewabove)
8257                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8258         else
8259                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8260         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8261         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8262 }
8263
8264 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8265 {
8266         int i;
8267         for (i = 0;i < numelements;i++)
8268                 outelement3i[i] = inelement3i[i] + adjust;
8269 }
8270
8271 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8272 extern cvar_t gl_vbo;
8273 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8274 {
8275         int deformindex;
8276         int firsttriangle;
8277         int numtriangles;
8278         int firstvertex;
8279         int endvertex;
8280         int numvertices;
8281         int surfacefirsttriangle;
8282         int surfacenumtriangles;
8283         int surfacefirstvertex;
8284         int surfaceendvertex;
8285         int surfacenumvertices;
8286         int batchnumvertices;
8287         int batchnumtriangles;
8288         int needsupdate;
8289         int i, j;
8290         qboolean gaps;
8291         qboolean dynamicvertex;
8292         float amplitude;
8293         float animpos;
8294         float scale;
8295         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8296         float waveparms[4];
8297         q3shaderinfo_deform_t *deform;
8298         const msurface_t *surface, *firstsurface;
8299         r_vertexmesh_t *vertexmesh;
8300         if (!texturenumsurfaces)
8301                 return;
8302         // find vertex range of this surface batch
8303         gaps = false;
8304         firstsurface = texturesurfacelist[0];
8305         firsttriangle = firstsurface->num_firsttriangle;
8306         batchnumvertices = 0;
8307         batchnumtriangles = 0;
8308         firstvertex = endvertex = firstsurface->num_firstvertex;
8309         for (i = 0;i < texturenumsurfaces;i++)
8310         {
8311                 surface = texturesurfacelist[i];
8312                 if (surface != firstsurface + i)
8313                         gaps = true;
8314                 surfacefirstvertex = surface->num_firstvertex;
8315                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8316                 surfacenumvertices = surface->num_vertices;
8317                 surfacenumtriangles = surface->num_triangles;
8318                 if (firstvertex > surfacefirstvertex)
8319                         firstvertex = surfacefirstvertex;
8320                 if (endvertex < surfaceendvertex)
8321                         endvertex = surfaceendvertex;
8322                 batchnumvertices += surfacenumvertices;
8323                 batchnumtriangles += surfacenumtriangles;
8324         }
8325
8326         // we now know the vertex range used, and if there are any gaps in it
8327         rsurface.batchfirstvertex = firstvertex;
8328         rsurface.batchnumvertices = endvertex - firstvertex;
8329         rsurface.batchfirsttriangle = firsttriangle;
8330         rsurface.batchnumtriangles = batchnumtriangles;
8331
8332         // this variable holds flags for which properties have been updated that
8333         // may require regenerating vertexmesh array...
8334         needsupdate = 0;
8335
8336         // check if any dynamic vertex processing must occur
8337         dynamicvertex = false;
8338
8339         // if there is a chance of animated vertex colors, it's a dynamic batch
8340         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8341         {
8342                 dynamicvertex = true;
8343                 batchneed |= BATCHNEED_NOGAPS;
8344                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8345         }
8346
8347         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8348         {
8349                 switch (deform->deform)
8350                 {
8351                 default:
8352                 case Q3DEFORM_PROJECTIONSHADOW:
8353                 case Q3DEFORM_TEXT0:
8354                 case Q3DEFORM_TEXT1:
8355                 case Q3DEFORM_TEXT2:
8356                 case Q3DEFORM_TEXT3:
8357                 case Q3DEFORM_TEXT4:
8358                 case Q3DEFORM_TEXT5:
8359                 case Q3DEFORM_TEXT6:
8360                 case Q3DEFORM_TEXT7:
8361                 case Q3DEFORM_NONE:
8362                         break;
8363                 case Q3DEFORM_AUTOSPRITE:
8364                         dynamicvertex = true;
8365                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8366                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8367                         break;
8368                 case Q3DEFORM_AUTOSPRITE2:
8369                         dynamicvertex = true;
8370                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8371                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8372                         break;
8373                 case Q3DEFORM_NORMAL:
8374                         dynamicvertex = true;
8375                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8376                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8377                         break;
8378                 case Q3DEFORM_WAVE:
8379                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8380                                 break; // if wavefunc is a nop, ignore this transform
8381                         dynamicvertex = true;
8382                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8383                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8384                         break;
8385                 case Q3DEFORM_BULGE:
8386                         dynamicvertex = true;
8387                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8388                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8389                         break;
8390                 case Q3DEFORM_MOVE:
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_NOGAPS;
8395                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8396                         break;
8397                 }
8398         }
8399         switch(rsurface.texture->tcgen.tcgen)
8400         {
8401         default:
8402         case Q3TCGEN_TEXTURE:
8403                 break;
8404         case Q3TCGEN_LIGHTMAP:
8405                 dynamicvertex = true;
8406                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8407                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8408                 break;
8409         case Q3TCGEN_VECTOR:
8410                 dynamicvertex = true;
8411                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8412                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8413                 break;
8414         case Q3TCGEN_ENVIRONMENT:
8415                 dynamicvertex = true;
8416                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8417                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8418                 break;
8419         }
8420         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8421         {
8422                 dynamicvertex = true;
8423                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8424                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8425         }
8426
8427         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8428         {
8429                 dynamicvertex = true;
8430                 batchneed |= BATCHNEED_NOGAPS;
8431                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8432         }
8433
8434         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8435         {
8436                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8437                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8438                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8439                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8440                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8441                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8442                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8443         }
8444
8445         // when the model data has no vertex buffer (dynamic mesh), we need to
8446         // eliminate gaps
8447         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8448                 batchneed |= BATCHNEED_NOGAPS;
8449
8450         // if needsupdate, we have to do a dynamic vertex batch for sure
8451         if (needsupdate & batchneed)
8452                 dynamicvertex = true;
8453
8454         // see if we need to build vertexmesh from arrays
8455         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8456                 dynamicvertex = true;
8457
8458         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8459         // also some drivers strongly dislike firstvertex
8460         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8461                 dynamicvertex = true;
8462
8463         rsurface.batchvertex3f = rsurface.modelvertex3f;
8464         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8465         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8466         rsurface.batchsvector3f = rsurface.modelsvector3f;
8467         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8468         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8469         rsurface.batchtvector3f = rsurface.modeltvector3f;
8470         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8471         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8472         rsurface.batchnormal3f = rsurface.modelnormal3f;
8473         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8474         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8475         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8476         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8477         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8478         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8479         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8480         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8481         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8482         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8483         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8484         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8485         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8486         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8487         rsurface.batchelement3i = rsurface.modelelement3i;
8488         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8489         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8490         rsurface.batchelement3s = rsurface.modelelement3s;
8491         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8492         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8493
8494         // if any dynamic vertex processing has to occur in software, we copy the
8495         // entire surface list together before processing to rebase the vertices
8496         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8497         //
8498         // if any gaps exist and we do not have a static vertex buffer, we have to
8499         // copy the surface list together to avoid wasting upload bandwidth on the
8500         // vertices in the gaps.
8501         //
8502         // if gaps exist and we have a static vertex buffer, we still have to
8503         // combine the index buffer ranges into one dynamic index buffer.
8504         //
8505         // in all cases we end up with data that can be drawn in one call.
8506
8507         if (!dynamicvertex)
8508         {
8509                 // static vertex data, just set pointers...
8510                 rsurface.batchgeneratedvertex = false;
8511                 // if there are gaps, we want to build a combined index buffer,
8512                 // otherwise use the original static buffer with an appropriate offset
8513                 if (gaps)
8514                 {
8515                         // build a new triangle elements array for this batch
8516                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8517                         rsurface.batchfirsttriangle = 0;
8518                         numtriangles = 0;
8519                         for (i = 0;i < texturenumsurfaces;i++)
8520                         {
8521                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8522                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8523                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8524                                 numtriangles += surfacenumtriangles;
8525                         }
8526                         rsurface.batchelement3i_indexbuffer = NULL;
8527                         rsurface.batchelement3i_bufferoffset = 0;
8528                         rsurface.batchelement3s = NULL;
8529                         rsurface.batchelement3s_indexbuffer = NULL;
8530                         rsurface.batchelement3s_bufferoffset = 0;
8531                         if (endvertex <= 65536)
8532                         {
8533                                 // make a 16bit (unsigned short) index array if possible
8534                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8535                                 for (i = 0;i < numtriangles*3;i++)
8536                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8537                         }
8538                 }
8539                 return;
8540         }
8541
8542         // something needs software processing, do it for real...
8543         // we only directly handle separate array data in this case and then
8544         // generate interleaved data if needed...
8545         rsurface.batchgeneratedvertex = true;
8546
8547         // now copy the vertex data into a combined array and make an index array
8548         // (this is what Quake3 does all the time)
8549         //if (gaps || rsurface.batchfirstvertex)
8550         {
8551                 rsurface.batchvertex3fbuffer = NULL;
8552                 rsurface.batchvertexmesh = NULL;
8553                 rsurface.batchvertexmeshbuffer = NULL;
8554                 rsurface.batchvertex3f = NULL;
8555                 rsurface.batchvertex3f_vertexbuffer = NULL;
8556                 rsurface.batchvertex3f_bufferoffset = 0;
8557                 rsurface.batchsvector3f = NULL;
8558                 rsurface.batchsvector3f_vertexbuffer = NULL;
8559                 rsurface.batchsvector3f_bufferoffset = 0;
8560                 rsurface.batchtvector3f = NULL;
8561                 rsurface.batchtvector3f_vertexbuffer = NULL;
8562                 rsurface.batchtvector3f_bufferoffset = 0;
8563                 rsurface.batchnormal3f = NULL;
8564                 rsurface.batchnormal3f_vertexbuffer = NULL;
8565                 rsurface.batchnormal3f_bufferoffset = 0;
8566                 rsurface.batchlightmapcolor4f = NULL;
8567                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8568                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8569                 rsurface.batchtexcoordtexture2f = NULL;
8570                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8571                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8572                 rsurface.batchtexcoordlightmap2f = NULL;
8573                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8574                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8575                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8576                 rsurface.batchelement3i_indexbuffer = NULL;
8577                 rsurface.batchelement3i_bufferoffset = 0;
8578                 rsurface.batchelement3s = NULL;
8579                 rsurface.batchelement3s_indexbuffer = NULL;
8580                 rsurface.batchelement3s_bufferoffset = 0;
8581                 // we'll only be setting up certain arrays as needed
8582                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8583                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8584                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8585                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8586                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8587                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8588                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8589                 {
8590                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8591                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8592                 }
8593                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8594                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8595                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8596                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8597                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8598                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8599                 numvertices = 0;
8600                 numtriangles = 0;
8601                 for (i = 0;i < texturenumsurfaces;i++)
8602                 {
8603                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8604                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8605                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8606                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8607                         // copy only the data requested
8608                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8609                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8610                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8611                         {
8612                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8613                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8614                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8615                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8616                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8617                                 {
8618                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8619                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8620                                 }
8621                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8622                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8623                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8624                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8625                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8626                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8627                         }
8628                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8629                         numvertices += surfacenumvertices;
8630                         numtriangles += surfacenumtriangles;
8631                 }
8632
8633                 // generate a 16bit index array as well if possible
8634                 // (in general, dynamic batches fit)
8635                 if (numvertices <= 65536)
8636                 {
8637                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8638                         for (i = 0;i < numtriangles*3;i++)
8639                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8640                 }
8641
8642                 // since we've copied everything, the batch now starts at 0
8643                 rsurface.batchfirstvertex = 0;
8644                 rsurface.batchnumvertices = batchnumvertices;
8645                 rsurface.batchfirsttriangle = 0;
8646                 rsurface.batchnumtriangles = batchnumtriangles;
8647         }
8648
8649         // q1bsp surfaces rendered in vertex color mode have to have colors
8650         // calculated based on lightstyles
8651         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8652         {
8653                 // generate color arrays for the surfaces in this list
8654                 int c[4];
8655                 int scale;
8656                 int size3;
8657                 const int *offsets;
8658                 const unsigned char *lm;
8659                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8660                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8661                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8662                 numvertices = 0;
8663                 for (i = 0;i < texturenumsurfaces;i++)
8664                 {
8665                         surface = texturesurfacelist[i];
8666                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8667                         surfacenumvertices = surface->num_vertices;
8668                         if (surface->lightmapinfo->samples)
8669                         {
8670                                 for (j = 0;j < surfacenumvertices;j++)
8671                                 {
8672                                         lm = surface->lightmapinfo->samples + offsets[j];
8673                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8674                                         VectorScale(lm, scale, c);
8675                                         if (surface->lightmapinfo->styles[1] != 255)
8676                                         {
8677                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8678                                                 lm += size3;
8679                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8680                                                 VectorMA(c, scale, lm, c);
8681                                                 if (surface->lightmapinfo->styles[2] != 255)
8682                                                 {
8683                                                         lm += size3;
8684                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8685                                                         VectorMA(c, scale, lm, c);
8686                                                         if (surface->lightmapinfo->styles[3] != 255)
8687                                                         {
8688                                                                 lm += size3;
8689                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8690                                                                 VectorMA(c, scale, lm, c);
8691                                                         }
8692                                                 }
8693                                         }
8694                                         c[0] >>= 7;
8695                                         c[1] >>= 7;
8696                                         c[2] >>= 7;
8697                                         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);
8698                                         numvertices++;
8699                                 }
8700                         }
8701                         else
8702                         {
8703                                 for (j = 0;j < surfacenumvertices;j++)
8704                                 {
8705                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8706                                         numvertices++;
8707                                 }
8708                         }
8709                 }
8710         }
8711
8712         // if vertices are deformed (sprite flares and things in maps, possibly
8713         // water waves, bulges and other deformations), modify the copied vertices
8714         // in place
8715         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8716         {
8717                 switch (deform->deform)
8718                 {
8719                 default:
8720                 case Q3DEFORM_PROJECTIONSHADOW:
8721                 case Q3DEFORM_TEXT0:
8722                 case Q3DEFORM_TEXT1:
8723                 case Q3DEFORM_TEXT2:
8724                 case Q3DEFORM_TEXT3:
8725                 case Q3DEFORM_TEXT4:
8726                 case Q3DEFORM_TEXT5:
8727                 case Q3DEFORM_TEXT6:
8728                 case Q3DEFORM_TEXT7:
8729                 case Q3DEFORM_NONE:
8730                         break;
8731                 case Q3DEFORM_AUTOSPRITE:
8732                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8733                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8734                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8735                         VectorNormalize(newforward);
8736                         VectorNormalize(newright);
8737                         VectorNormalize(newup);
8738 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8739 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8740 //                      rsurface.batchvertex3f_bufferoffset = 0;
8741 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8742 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8743 //                      rsurface.batchsvector3f_bufferoffset = 0;
8744 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8745 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8746 //                      rsurface.batchtvector3f_bufferoffset = 0;
8747 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8748 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8749 //                      rsurface.batchnormal3f_bufferoffset = 0;
8750                         // a single autosprite surface can contain multiple sprites...
8751                         for (j = 0;j < batchnumvertices - 3;j += 4)
8752                         {
8753                                 VectorClear(center);
8754                                 for (i = 0;i < 4;i++)
8755                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8756                                 VectorScale(center, 0.25f, center);
8757                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8758                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8759                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8760                                 for (i = 0;i < 4;i++)
8761                                 {
8762                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8763                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8764                                 }
8765                         }
8766                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8767                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8768                         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);
8769                         break;
8770                 case Q3DEFORM_AUTOSPRITE2:
8771                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8772                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8773                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8774                         VectorNormalize(newforward);
8775                         VectorNormalize(newright);
8776                         VectorNormalize(newup);
8777 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8778 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8779 //                      rsurface.batchvertex3f_bufferoffset = 0;
8780                         {
8781                                 const float *v1, *v2;
8782                                 vec3_t start, end;
8783                                 float f, l;
8784                                 struct
8785                                 {
8786                                         float length2;
8787                                         const float *v1;
8788                                         const float *v2;
8789                                 }
8790                                 shortest[2];
8791                                 memset(shortest, 0, sizeof(shortest));
8792                                 // a single autosprite surface can contain multiple sprites...
8793                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8794                                 {
8795                                         VectorClear(center);
8796                                         for (i = 0;i < 4;i++)
8797                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8798                                         VectorScale(center, 0.25f, center);
8799                                         // find the two shortest edges, then use them to define the
8800                                         // axis vectors for rotating around the central axis
8801                                         for (i = 0;i < 6;i++)
8802                                         {
8803                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8804                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8805                                                 l = VectorDistance2(v1, v2);
8806                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8807                                                 if (v1[2] != v2[2])
8808                                                         l += (1.0f / 1024.0f);
8809                                                 if (shortest[0].length2 > l || i == 0)
8810                                                 {
8811                                                         shortest[1] = shortest[0];
8812                                                         shortest[0].length2 = l;
8813                                                         shortest[0].v1 = v1;
8814                                                         shortest[0].v2 = v2;
8815                                                 }
8816                                                 else if (shortest[1].length2 > l || i == 1)
8817                                                 {
8818                                                         shortest[1].length2 = l;
8819                                                         shortest[1].v1 = v1;
8820                                                         shortest[1].v2 = v2;
8821                                                 }
8822                                         }
8823                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8824                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8825                                         // this calculates the right vector from the shortest edge
8826                                         // and the up vector from the edge midpoints
8827                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8828                                         VectorNormalize(right);
8829                                         VectorSubtract(end, start, up);
8830                                         VectorNormalize(up);
8831                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8832                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8833                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8834                                         VectorNegate(forward, forward);
8835                                         VectorReflect(forward, 0, up, forward);
8836                                         VectorNormalize(forward);
8837                                         CrossProduct(up, forward, newright);
8838                                         VectorNormalize(newright);
8839                                         // rotate the quad around the up axis vector, this is made
8840                                         // especially easy by the fact we know the quad is flat,
8841                                         // so we only have to subtract the center position and
8842                                         // measure distance along the right vector, and then
8843                                         // multiply that by the newright vector and add back the
8844                                         // center position
8845                                         // we also need to subtract the old position to undo the
8846                                         // displacement from the center, which we do with a
8847                                         // DotProduct, the subtraction/addition of center is also
8848                                         // optimized into DotProducts here
8849                                         l = DotProduct(right, center);
8850                                         for (i = 0;i < 4;i++)
8851                                         {
8852                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8853                                                 f = DotProduct(right, v1) - l;
8854                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8855                                         }
8856                                 }
8857                         }
8858                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8859                         {
8860 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8861 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8862 //                              rsurface.batchnormal3f_bufferoffset = 0;
8863                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8864                         }
8865                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8866                         {
8867 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8869 //                              rsurface.batchsvector3f_bufferoffset = 0;
8870 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8872 //                              rsurface.batchtvector3f_bufferoffset = 0;
8873                                 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);
8874                         }
8875                         break;
8876                 case Q3DEFORM_NORMAL:
8877                         // deform the normals to make reflections wavey
8878                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8879                         rsurface.batchnormal3f_vertexbuffer = NULL;
8880                         rsurface.batchnormal3f_bufferoffset = 0;
8881                         for (j = 0;j < batchnumvertices;j++)
8882                         {
8883                                 float vertex[3];
8884                                 float *normal = rsurface.batchnormal3f + 3*j;
8885                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8886                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8887                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8888                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
8889                                 VectorNormalize(normal);
8890                         }
8891                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8892                         {
8893 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8894 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8895 //                              rsurface.batchsvector3f_bufferoffset = 0;
8896 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8897 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8898 //                              rsurface.batchtvector3f_bufferoffset = 0;
8899                                 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);
8900                         }
8901                         break;
8902                 case Q3DEFORM_WAVE:
8903                         // deform vertex array to make wavey water and flags and such
8904                         waveparms[0] = deform->waveparms[0];
8905                         waveparms[1] = deform->waveparms[1];
8906                         waveparms[2] = deform->waveparms[2];
8907                         waveparms[3] = deform->waveparms[3];
8908                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8909                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8910                         // this is how a divisor of vertex influence on deformation
8911                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8912                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8913 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8914 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8915 //                      rsurface.batchvertex3f_bufferoffset = 0;
8916 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8917 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8918 //                      rsurface.batchnormal3f_bufferoffset = 0;
8919                         for (j = 0;j < batchnumvertices;j++)
8920                         {
8921                                 // if the wavefunc depends on time, evaluate it per-vertex
8922                                 if (waveparms[3])
8923                                 {
8924                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8925                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8926                                 }
8927                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8928                         }
8929                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8930                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8931                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8932                         {
8933 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8934 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8935 //                              rsurface.batchsvector3f_bufferoffset = 0;
8936 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8937 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8938 //                              rsurface.batchtvector3f_bufferoffset = 0;
8939                                 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);
8940                         }
8941                         break;
8942                 case Q3DEFORM_BULGE:
8943                         // deform vertex array to make the surface have moving bulges
8944 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8945 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8946 //                      rsurface.batchvertex3f_bufferoffset = 0;
8947 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8948 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8949 //                      rsurface.batchnormal3f_bufferoffset = 0;
8950                         for (j = 0;j < batchnumvertices;j++)
8951                         {
8952                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
8953                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8954                         }
8955                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8956                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8957                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8958                         {
8959 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8960 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8961 //                              rsurface.batchsvector3f_bufferoffset = 0;
8962 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8963 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8964 //                              rsurface.batchtvector3f_bufferoffset = 0;
8965                                 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);
8966                         }
8967                         break;
8968                 case Q3DEFORM_MOVE:
8969                         // deform vertex array
8970                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8971                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8972                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8973                         VectorScale(deform->parms, scale, waveparms);
8974 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8975 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8976 //                      rsurface.batchvertex3f_bufferoffset = 0;
8977                         for (j = 0;j < batchnumvertices;j++)
8978                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8979                         break;
8980                 }
8981         }
8982
8983         // generate texcoords based on the chosen texcoord source
8984         switch(rsurface.texture->tcgen.tcgen)
8985         {
8986         default:
8987         case Q3TCGEN_TEXTURE:
8988                 break;
8989         case Q3TCGEN_LIGHTMAP:
8990 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8991 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8992 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8993                 if (rsurface.batchtexcoordlightmap2f)
8994                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8995                 break;
8996         case Q3TCGEN_VECTOR:
8997 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8998 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8999 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9000                 for (j = 0;j < batchnumvertices;j++)
9001                 {
9002                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9003                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9004                 }
9005                 break;
9006         case Q3TCGEN_ENVIRONMENT:
9007                 // make environment reflections using a spheremap
9008                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9009                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9010                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9011                 for (j = 0;j < batchnumvertices;j++)
9012                 {
9013                         // identical to Q3A's method, but executed in worldspace so
9014                         // carried models can be shiny too
9015
9016                         float viewer[3], d, reflected[3], worldreflected[3];
9017
9018                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9019                         // VectorNormalize(viewer);
9020
9021                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9022
9023                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9024                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9025                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9026                         // note: this is proportinal to viewer, so we can normalize later
9027
9028                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9029                         VectorNormalize(worldreflected);
9030
9031                         // note: this sphere map only uses world x and z!
9032                         // so positive and negative y will LOOK THE SAME.
9033                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9034                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9035                 }
9036                 break;
9037         }
9038         // the only tcmod that needs software vertex processing is turbulent, so
9039         // check for it here and apply the changes if needed
9040         // and we only support that as the first one
9041         // (handling a mixture of turbulent and other tcmods would be problematic
9042         //  without punting it entirely to a software path)
9043         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9044         {
9045                 amplitude = rsurface.texture->tcmods[0].parms[1];
9046                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9047 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9048 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9049 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9050                 for (j = 0;j < batchnumvertices;j++)
9051                 {
9052                         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);
9053                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9054                 }
9055         }
9056
9057         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9058         {
9059                 // convert the modified arrays to vertex structs
9060 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9061 //              rsurface.batchvertexmeshbuffer = NULL;
9062                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9063                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9064                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9065                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9066                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9067                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9068                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9069                 {
9070                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9071                         {
9072                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9073                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9074                         }
9075                 }
9076                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9077                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9078                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9079                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9080                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9081                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9082                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9083                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9084                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9085         }
9086 }
9087
9088 void RSurf_DrawBatch(void)
9089 {
9090         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9091         // through the pipeline, killing it earlier in the pipeline would have
9092         // per-surface overhead rather than per-batch overhead, so it's best to
9093         // reject it here, before it hits glDraw.
9094         if (rsurface.batchnumtriangles == 0)
9095                 return;
9096 #if 0
9097         // batch debugging code
9098         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9099         {
9100                 int i;
9101                 int j;
9102                 int c;
9103                 const int *e;
9104                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9105                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9106                 {
9107                         c = e[i];
9108                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9109                         {
9110                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9111                                 {
9112                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9113                                                 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);
9114                                         break;
9115                                 }
9116                         }
9117                 }
9118         }
9119 #endif
9120         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);
9121 }
9122
9123 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9124 {
9125         // pick the closest matching water plane
9126         int planeindex, vertexindex, bestplaneindex = -1;
9127         float d, bestd;
9128         vec3_t vert;
9129         const float *v;
9130         r_waterstate_waterplane_t *p;
9131         qboolean prepared = false;
9132         bestd = 0;
9133         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9134         {
9135                 if(p->camera_entity != rsurface.texture->camera_entity)
9136                         continue;
9137                 d = 0;
9138                 if(!prepared)
9139                 {
9140                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9141                         prepared = true;
9142                         if(rsurface.batchnumvertices == 0)
9143                                 break;
9144                 }
9145                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9146                 {
9147                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9148                         d += fabs(PlaneDiff(vert, &p->plane));
9149                 }
9150                 if (bestd > d || bestplaneindex < 0)
9151                 {
9152                         bestd = d;
9153                         bestplaneindex = planeindex;
9154                 }
9155         }
9156         return bestplaneindex;
9157         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9158         // this situation though, as it might be better to render single larger
9159         // batches with useless stuff (backface culled for example) than to
9160         // render multiple smaller batches
9161 }
9162
9163 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9164 {
9165         int i;
9166         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9167         rsurface.passcolor4f_vertexbuffer = 0;
9168         rsurface.passcolor4f_bufferoffset = 0;
9169         for (i = 0;i < rsurface.batchnumvertices;i++)
9170                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9171 }
9172
9173 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9174 {
9175         int i;
9176         float f;
9177         const float *v;
9178         const float *c;
9179         float *c2;
9180         if (rsurface.passcolor4f)
9181         {
9182                 // generate color arrays
9183                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9184                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9185                 rsurface.passcolor4f_vertexbuffer = 0;
9186                 rsurface.passcolor4f_bufferoffset = 0;
9187                 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)
9188                 {
9189                         f = RSurf_FogVertex(v);
9190                         c2[0] = c[0] * f;
9191                         c2[1] = c[1] * f;
9192                         c2[2] = c[2] * f;
9193                         c2[3] = c[3];
9194                 }
9195         }
9196         else
9197         {
9198                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9199                 rsurface.passcolor4f_vertexbuffer = 0;
9200                 rsurface.passcolor4f_bufferoffset = 0;
9201                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9202                 {
9203                         f = RSurf_FogVertex(v);
9204                         c2[0] = f;
9205                         c2[1] = f;
9206                         c2[2] = f;
9207                         c2[3] = 1;
9208                 }
9209         }
9210 }
9211
9212 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9213 {
9214         int i;
9215         float f;
9216         const float *v;
9217         const float *c;
9218         float *c2;
9219         if (!rsurface.passcolor4f)
9220                 return;
9221         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9222         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9223         rsurface.passcolor4f_vertexbuffer = 0;
9224         rsurface.passcolor4f_bufferoffset = 0;
9225         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)
9226         {
9227                 f = RSurf_FogVertex(v);
9228                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9229                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9230                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9231                 c2[3] = c[3];
9232         }
9233 }
9234
9235 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9236 {
9237         int i;
9238         const float *c;
9239         float *c2;
9240         if (!rsurface.passcolor4f)
9241                 return;
9242         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9243         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9244         rsurface.passcolor4f_vertexbuffer = 0;
9245         rsurface.passcolor4f_bufferoffset = 0;
9246         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9247         {
9248                 c2[0] = c[0] * r;
9249                 c2[1] = c[1] * g;
9250                 c2[2] = c[2] * b;
9251                 c2[3] = c[3] * a;
9252         }
9253 }
9254
9255 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9256 {
9257         int i;
9258         const float *c;
9259         float *c2;
9260         if (!rsurface.passcolor4f)
9261                 return;
9262         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9263         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9264         rsurface.passcolor4f_vertexbuffer = 0;
9265         rsurface.passcolor4f_bufferoffset = 0;
9266         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9267         {
9268                 c2[0] = c[0] + r_refdef.scene.ambient;
9269                 c2[1] = c[1] + r_refdef.scene.ambient;
9270                 c2[2] = c[2] + r_refdef.scene.ambient;
9271                 c2[3] = c[3];
9272         }
9273 }
9274
9275 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9276 {
9277         // TODO: optimize
9278         rsurface.passcolor4f = NULL;
9279         rsurface.passcolor4f_vertexbuffer = 0;
9280         rsurface.passcolor4f_bufferoffset = 0;
9281         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9282         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9283         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9284         GL_Color(r, g, b, a);
9285         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9286         RSurf_DrawBatch();
9287 }
9288
9289 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9290 {
9291         // TODO: optimize applyfog && applycolor case
9292         // just apply fog if necessary, and tint the fog color array if necessary
9293         rsurface.passcolor4f = NULL;
9294         rsurface.passcolor4f_vertexbuffer = 0;
9295         rsurface.passcolor4f_bufferoffset = 0;
9296         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9297         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9298         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9299         GL_Color(r, g, b, a);
9300         RSurf_DrawBatch();
9301 }
9302
9303 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9304 {
9305         // TODO: optimize
9306         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9307         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9308         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9309         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9310         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9311         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9312         GL_Color(r, g, b, a);
9313         RSurf_DrawBatch();
9314 }
9315
9316 static void RSurf_DrawBatch_GL11_ClampColor(void)
9317 {
9318         int i;
9319         const float *c1;
9320         float *c2;
9321         if (!rsurface.passcolor4f)
9322                 return;
9323         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9324         {
9325                 c2[0] = bound(0.0f, c1[0], 1.0f);
9326                 c2[1] = bound(0.0f, c1[1], 1.0f);
9327                 c2[2] = bound(0.0f, c1[2], 1.0f);
9328                 c2[3] = bound(0.0f, c1[3], 1.0f);
9329         }
9330 }
9331
9332 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9333 {
9334         int i;
9335         float f;
9336         const float *v;
9337         const float *n;
9338         float *c;
9339         //vec3_t eyedir;
9340
9341         // fake shading
9342         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9343         rsurface.passcolor4f_vertexbuffer = 0;
9344         rsurface.passcolor4f_bufferoffset = 0;
9345         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)
9346         {
9347                 f = -DotProduct(r_refdef.view.forward, n);
9348                 f = max(0, f);
9349                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9350                 f *= r_refdef.lightmapintensity;
9351                 Vector4Set(c, f, f, f, 1);
9352         }
9353 }
9354
9355 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9356 {
9357         RSurf_DrawBatch_GL11_ApplyFakeLight();
9358         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9359         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9360         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9361         GL_Color(r, g, b, a);
9362         RSurf_DrawBatch();
9363 }
9364
9365 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9366 {
9367         int i;
9368         float f;
9369         float alpha;
9370         const float *v;
9371         const float *n;
9372         float *c;
9373         vec3_t ambientcolor;
9374         vec3_t diffusecolor;
9375         vec3_t lightdir;
9376         // TODO: optimize
9377         // model lighting
9378         VectorCopy(rsurface.modellight_lightdir, lightdir);
9379         f = 0.5f * r_refdef.lightmapintensity;
9380         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9381         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9382         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9383         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9384         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9385         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9386         alpha = *a;
9387         if (VectorLength2(diffusecolor) > 0)
9388         {
9389                 // q3-style directional shading
9390                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9391                 rsurface.passcolor4f_vertexbuffer = 0;
9392                 rsurface.passcolor4f_bufferoffset = 0;
9393                 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)
9394                 {
9395                         if ((f = DotProduct(n, lightdir)) > 0)
9396                                 VectorMA(ambientcolor, f, diffusecolor, c);
9397                         else
9398                                 VectorCopy(ambientcolor, c);
9399                         c[3] = alpha;
9400                 }
9401                 *r = 1;
9402                 *g = 1;
9403                 *b = 1;
9404                 *a = 1;
9405                 *applycolor = false;
9406         }
9407         else
9408         {
9409                 *r = ambientcolor[0];
9410                 *g = ambientcolor[1];
9411                 *b = ambientcolor[2];
9412                 rsurface.passcolor4f = NULL;
9413                 rsurface.passcolor4f_vertexbuffer = 0;
9414                 rsurface.passcolor4f_bufferoffset = 0;
9415         }
9416 }
9417
9418 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9419 {
9420         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9421         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9422         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9423         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9424         GL_Color(r, g, b, a);
9425         RSurf_DrawBatch();
9426 }
9427
9428 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9429 {
9430         int i;
9431         float f;
9432         const float *v;
9433         float *c;
9434
9435         // fake shading
9436         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9437         rsurface.passcolor4f_vertexbuffer = 0;
9438         rsurface.passcolor4f_bufferoffset = 0;
9439
9440         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9441         {
9442                 f = 1 - RSurf_FogVertex(v);
9443                 c[0] = r;
9444                 c[1] = g;
9445                 c[2] = b;
9446                 c[3] = f * a;
9447         }
9448 }
9449
9450 void RSurf_SetupDepthAndCulling(void)
9451 {
9452         // submodels are biased to avoid z-fighting with world surfaces that they
9453         // may be exactly overlapping (avoids z-fighting artifacts on certain
9454         // doors and things in Quake maps)
9455         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9456         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9457         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9458         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9459 }
9460
9461 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9462 {
9463         // transparent sky would be ridiculous
9464         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9465                 return;
9466         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9467         skyrenderlater = true;
9468         RSurf_SetupDepthAndCulling();
9469         GL_DepthMask(true);
9470         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9471         // skymasking on them, and Quake3 never did sky masking (unlike
9472         // software Quake and software Quake2), so disable the sky masking
9473         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9474         // and skymasking also looks very bad when noclipping outside the
9475         // level, so don't use it then either.
9476         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9477         {
9478                 R_Mesh_ResetTextureState();
9479                 if (skyrendermasked)
9480                 {
9481                         R_SetupShader_DepthOrShadow();
9482                         // depth-only (masking)
9483                         GL_ColorMask(0,0,0,0);
9484                         // just to make sure that braindead drivers don't draw
9485                         // anything despite that colormask...
9486                         GL_BlendFunc(GL_ZERO, GL_ONE);
9487                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9488                         if (rsurface.batchvertex3fbuffer)
9489                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9490                         else
9491                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9492                 }
9493                 else
9494                 {
9495                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9496                         // fog sky
9497                         GL_BlendFunc(GL_ONE, GL_ZERO);
9498                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9499                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9500                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9501                 }
9502                 RSurf_DrawBatch();
9503                 if (skyrendermasked)
9504                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9505         }
9506         R_Mesh_ResetTextureState();
9507         GL_Color(1, 1, 1, 1);
9508 }
9509
9510 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9511 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9512 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9513 {
9514         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9515                 return;
9516         if (prepass)
9517         {
9518                 // render screenspace normalmap to texture
9519                 GL_DepthMask(true);
9520                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9521                 RSurf_DrawBatch();
9522         }
9523
9524         // bind lightmap texture
9525
9526         // water/refraction/reflection/camera surfaces have to be handled specially
9527         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9528         {
9529                 int start, end, startplaneindex;
9530                 for (start = 0;start < texturenumsurfaces;start = end)
9531                 {
9532                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9533                         if(startplaneindex < 0)
9534                         {
9535                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9536                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9537                                 end = start + 1;
9538                                 continue;
9539                         }
9540                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9541                                 ;
9542                         // now that we have a batch using the same planeindex, render it
9543                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9544                         {
9545                                 // render water or distortion background
9546                                 GL_DepthMask(true);
9547                                 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));
9548                                 RSurf_DrawBatch();
9549                                 // blend surface on top
9550                                 GL_DepthMask(false);
9551                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9552                                 RSurf_DrawBatch();
9553                         }
9554                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9555                         {
9556                                 // render surface with reflection texture as input
9557                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9558                                 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));
9559                                 RSurf_DrawBatch();
9560                         }
9561                 }
9562                 return;
9563         }
9564
9565         // render surface batch normally
9566         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9567         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9568         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9569                 GL_AlphaTest(true);
9570         RSurf_DrawBatch();
9571         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9572                 GL_AlphaTest(false);
9573 }
9574
9575 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9576 {
9577         // OpenGL 1.3 path - anything not completely ancient
9578         qboolean applycolor;
9579         qboolean applyfog;
9580         int layerindex;
9581         const texturelayer_t *layer;
9582         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);
9583         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9584
9585         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9586         {
9587                 vec4_t layercolor;
9588                 int layertexrgbscale;
9589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9590                 {
9591                         if (layerindex == 0)
9592                                 GL_AlphaTest(true);
9593                         else
9594                         {
9595                                 GL_AlphaTest(false);
9596                                 GL_DepthFunc(GL_EQUAL);
9597                         }
9598                 }
9599                 GL_DepthMask(layer->depthmask && writedepth);
9600                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9601                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9602                 {
9603                         layertexrgbscale = 4;
9604                         VectorScale(layer->color, 0.25f, layercolor);
9605                 }
9606                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9607                 {
9608                         layertexrgbscale = 2;
9609                         VectorScale(layer->color, 0.5f, layercolor);
9610                 }
9611                 else
9612                 {
9613                         layertexrgbscale = 1;
9614                         VectorScale(layer->color, 1.0f, layercolor);
9615                 }
9616                 layercolor[3] = layer->color[3];
9617                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9618                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9619                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9620                 switch (layer->type)
9621                 {
9622                 case TEXTURELAYERTYPE_LITTEXTURE:
9623                         // single-pass lightmapped texture with 2x rgbscale
9624                         R_Mesh_TexBind(0, r_texture_white);
9625                         R_Mesh_TexMatrix(0, NULL);
9626                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9627                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9628                         R_Mesh_TexBind(1, layer->texture);
9629                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9630                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9631                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9632                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9633                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9634                         else if (FAKELIGHT_ENABLED)
9635                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9636                         else if (rsurface.uselightmaptexture)
9637                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9638                         else
9639                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9640                         break;
9641                 case TEXTURELAYERTYPE_TEXTURE:
9642                         // singletexture unlit texture with transparency support
9643                         R_Mesh_TexBind(0, layer->texture);
9644                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9645                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9646                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9647                         R_Mesh_TexBind(1, 0);
9648                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9649                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9650                         break;
9651                 case TEXTURELAYERTYPE_FOG:
9652                         // singletexture fogging
9653                         if (layer->texture)
9654                         {
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                         }
9660                         else
9661                         {
9662                                 R_Mesh_TexBind(0, 0);
9663                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9664                         }
9665                         R_Mesh_TexBind(1, 0);
9666                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9667                         // generate a color array for the fog pass
9668                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9669                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9670                         RSurf_DrawBatch();
9671                         break;
9672                 default:
9673                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9674                 }
9675         }
9676         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9677         {
9678                 GL_DepthFunc(GL_LEQUAL);
9679                 GL_AlphaTest(false);
9680         }
9681 }
9682
9683 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9684 {
9685         // OpenGL 1.1 - crusty old voodoo path
9686         qboolean applyfog;
9687         int layerindex;
9688         const texturelayer_t *layer;
9689         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);
9690         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9691
9692         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9693         {
9694                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9695                 {
9696                         if (layerindex == 0)
9697                                 GL_AlphaTest(true);
9698                         else
9699                         {
9700                                 GL_AlphaTest(false);
9701                                 GL_DepthFunc(GL_EQUAL);
9702                         }
9703                 }
9704                 GL_DepthMask(layer->depthmask && writedepth);
9705                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9706                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9707                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9708                 switch (layer->type)
9709                 {
9710                 case TEXTURELAYERTYPE_LITTEXTURE:
9711                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9712                         {
9713                                 // two-pass lit texture with 2x rgbscale
9714                                 // first the lightmap pass
9715                                 R_Mesh_TexBind(0, r_texture_white);
9716                                 R_Mesh_TexMatrix(0, NULL);
9717                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9718                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9719                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9720                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9721                                 else if (FAKELIGHT_ENABLED)
9722                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9723                                 else if (rsurface.uselightmaptexture)
9724                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9725                                 else
9726                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9727                                 // then apply the texture to it
9728                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9729                                 R_Mesh_TexBind(0, layer->texture);
9730                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9731                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9732                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9733                                 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);
9734                         }
9735                         else
9736                         {
9737                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9738                                 R_Mesh_TexBind(0, layer->texture);
9739                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9740                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9741                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9742                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9743                                         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);
9744                                 else
9745                                         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);
9746                         }
9747                         break;
9748                 case TEXTURELAYERTYPE_TEXTURE:
9749                         // singletexture unlit texture with 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                         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);
9755                         break;
9756                 case TEXTURELAYERTYPE_FOG:
9757                         // singletexture fogging
9758                         if (layer->texture)
9759                         {
9760                                 R_Mesh_TexBind(0, layer->texture);
9761                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9762                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9763                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9764                         }
9765                         else
9766                         {
9767                                 R_Mesh_TexBind(0, 0);
9768                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9769                         }
9770                         // generate a color array for the fog pass
9771                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9772                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9773                         RSurf_DrawBatch();
9774                         break;
9775                 default:
9776                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9777                 }
9778         }
9779         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9780         {
9781                 GL_DepthFunc(GL_LEQUAL);
9782                 GL_AlphaTest(false);
9783         }
9784 }
9785
9786 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9787 {
9788         int vi;
9789         int j;
9790         r_vertexgeneric_t *batchvertex;
9791         float c[4];
9792
9793 //      R_Mesh_ResetTextureState();
9794         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9795
9796         if(rsurface.texture && rsurface.texture->currentskinframe)
9797         {
9798                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9799                 c[3] *= rsurface.texture->currentalpha;
9800         }
9801         else
9802         {
9803                 c[0] = 1;
9804                 c[1] = 0;
9805                 c[2] = 1;
9806                 c[3] = 1;
9807         }
9808
9809         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9810         {
9811                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9812                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9813                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9814         }
9815
9816         // brighten it up (as texture value 127 means "unlit")
9817         c[0] *= 2 * r_refdef.view.colorscale;
9818         c[1] *= 2 * r_refdef.view.colorscale;
9819         c[2] *= 2 * r_refdef.view.colorscale;
9820
9821         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9822                 c[3] *= r_wateralpha.value;
9823
9824         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9825         {
9826                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9827                 GL_DepthMask(false);
9828         }
9829         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9830         {
9831                 GL_BlendFunc(GL_ONE, GL_ONE);
9832                 GL_DepthMask(false);
9833         }
9834         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9835         {
9836                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9837                 GL_DepthMask(false);
9838         }
9839         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9840         {
9841                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9842                 GL_DepthMask(false);
9843         }
9844         else
9845         {
9846                 GL_BlendFunc(GL_ONE, GL_ZERO);
9847                 GL_DepthMask(writedepth);
9848         }
9849
9850         if (r_showsurfaces.integer == 3)
9851         {
9852                 rsurface.passcolor4f = NULL;
9853
9854                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9855                 {
9856                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9857
9858                         rsurface.passcolor4f = NULL;
9859                         rsurface.passcolor4f_vertexbuffer = 0;
9860                         rsurface.passcolor4f_bufferoffset = 0;
9861                 }
9862                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9863                 {
9864                         qboolean applycolor = true;
9865                         float one = 1.0;
9866
9867                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9868
9869                         r_refdef.lightmapintensity = 1;
9870                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9871                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9872                 }
9873                 else if (FAKELIGHT_ENABLED)
9874                 {
9875                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9876
9877                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9878                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9879                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9880                 }
9881                 else
9882                 {
9883                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9884
9885                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9886                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9887                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9888                 }
9889
9890                 if(!rsurface.passcolor4f)
9891                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9892
9893                 RSurf_DrawBatch_GL11_ApplyAmbient();
9894                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9895                 if(r_refdef.fogenabled)
9896                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9897                 RSurf_DrawBatch_GL11_ClampColor();
9898
9899                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9900                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9901                 RSurf_DrawBatch();
9902         }
9903         else if (!r_refdef.view.showdebug)
9904         {
9905                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9906                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9907                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9908                 {
9909                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9910                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9911                 }
9912                 R_Mesh_PrepareVertices_Generic_Unlock();
9913                 RSurf_DrawBatch();
9914         }
9915         else if (r_showsurfaces.integer == 4)
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                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9922                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9923                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9924                 }
9925                 R_Mesh_PrepareVertices_Generic_Unlock();
9926                 RSurf_DrawBatch();
9927         }
9928         else if (r_showsurfaces.integer == 2)
9929         {
9930                 const int *e;
9931                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9932                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9933                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9934                 {
9935                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9936                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9937                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9938                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9939                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9940                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9941                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9942                 }
9943                 R_Mesh_PrepareVertices_Generic_Unlock();
9944                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9945         }
9946         else
9947         {
9948                 int texturesurfaceindex;
9949                 int k;
9950                 const msurface_t *surface;
9951                 float surfacecolor4f[4];
9952                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9953                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9954                 vi = 0;
9955                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9956                 {
9957                         surface = texturesurfacelist[texturesurfaceindex];
9958                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9959                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9960                         for (j = 0;j < surface->num_vertices;j++)
9961                         {
9962                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9963                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9964                                 vi++;
9965                         }
9966                 }
9967                 R_Mesh_PrepareVertices_Generic_Unlock();
9968                 RSurf_DrawBatch();
9969         }
9970 }
9971
9972 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9973 {
9974         CHECKGLERROR
9975         RSurf_SetupDepthAndCulling();
9976         if (r_showsurfaces.integer)
9977         {
9978                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9979                 return;
9980         }
9981         switch (vid.renderpath)
9982         {
9983         case RENDERPATH_GL20:
9984         case RENDERPATH_D3D9:
9985         case RENDERPATH_D3D10:
9986         case RENDERPATH_D3D11:
9987         case RENDERPATH_SOFT:
9988         case RENDERPATH_GLES2:
9989                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9990                 break;
9991         case RENDERPATH_GL13:
9992         case RENDERPATH_GLES1:
9993                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9994                 break;
9995         case RENDERPATH_GL11:
9996                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9997                 break;
9998         }
9999         CHECKGLERROR
10000 }
10001
10002 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10003 {
10004         CHECKGLERROR
10005         RSurf_SetupDepthAndCulling();
10006         if (r_showsurfaces.integer)
10007         {
10008                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10009                 return;
10010         }
10011         switch (vid.renderpath)
10012         {
10013         case RENDERPATH_GL20:
10014         case RENDERPATH_D3D9:
10015         case RENDERPATH_D3D10:
10016         case RENDERPATH_D3D11:
10017         case RENDERPATH_SOFT:
10018         case RENDERPATH_GLES2:
10019                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10020                 break;
10021         case RENDERPATH_GL13:
10022         case RENDERPATH_GLES1:
10023                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10024                 break;
10025         case RENDERPATH_GL11:
10026                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10027                 break;
10028         }
10029         CHECKGLERROR
10030 }
10031
10032 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10033 {
10034         int i, j;
10035         int texturenumsurfaces, endsurface;
10036         texture_t *texture;
10037         const msurface_t *surface;
10038         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10039
10040         // if the model is static it doesn't matter what value we give for
10041         // wantnormals and wanttangents, so this logic uses only rules applicable
10042         // to a model, knowing that they are meaningless otherwise
10043         if (ent == r_refdef.scene.worldentity)
10044                 RSurf_ActiveWorldEntity();
10045         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10046                 RSurf_ActiveModelEntity(ent, false, false, false);
10047         else
10048         {
10049                 switch (vid.renderpath)
10050                 {
10051                 case RENDERPATH_GL20:
10052                 case RENDERPATH_D3D9:
10053                 case RENDERPATH_D3D10:
10054                 case RENDERPATH_D3D11:
10055                 case RENDERPATH_SOFT:
10056                 case RENDERPATH_GLES2:
10057                         RSurf_ActiveModelEntity(ent, true, true, false);
10058                         break;
10059                 case RENDERPATH_GL11:
10060                 case RENDERPATH_GL13:
10061                 case RENDERPATH_GLES1:
10062                         RSurf_ActiveModelEntity(ent, true, false, false);
10063                         break;
10064                 }
10065         }
10066
10067         if (r_transparentdepthmasking.integer)
10068         {
10069                 qboolean setup = false;
10070                 for (i = 0;i < numsurfaces;i = j)
10071                 {
10072                         j = i + 1;
10073                         surface = rsurface.modelsurfaces + surfacelist[i];
10074                         texture = surface->texture;
10075                         rsurface.texture = R_GetCurrentTexture(texture);
10076                         rsurface.lightmaptexture = NULL;
10077                         rsurface.deluxemaptexture = NULL;
10078                         rsurface.uselightmaptexture = false;
10079                         // scan ahead until we find a different texture
10080                         endsurface = min(i + 1024, numsurfaces);
10081                         texturenumsurfaces = 0;
10082                         texturesurfacelist[texturenumsurfaces++] = surface;
10083                         for (;j < endsurface;j++)
10084                         {
10085                                 surface = rsurface.modelsurfaces + surfacelist[j];
10086                                 if (texture != surface->texture)
10087                                         break;
10088                                 texturesurfacelist[texturenumsurfaces++] = surface;
10089                         }
10090                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10091                                 continue;
10092                         // render the range of surfaces as depth
10093                         if (!setup)
10094                         {
10095                                 setup = true;
10096                                 GL_ColorMask(0,0,0,0);
10097                                 GL_Color(1,1,1,1);
10098                                 GL_DepthTest(true);
10099                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10100                                 GL_DepthMask(true);
10101 //                              R_Mesh_ResetTextureState();
10102                                 R_SetupShader_DepthOrShadow();
10103                         }
10104                         RSurf_SetupDepthAndCulling();
10105                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10106                         if (rsurface.batchvertex3fbuffer)
10107                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10108                         else
10109                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10110                         RSurf_DrawBatch();
10111                 }
10112                 if (setup)
10113                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10114         }
10115
10116         for (i = 0;i < numsurfaces;i = j)
10117         {
10118                 j = i + 1;
10119                 surface = rsurface.modelsurfaces + surfacelist[i];
10120                 texture = surface->texture;
10121                 rsurface.texture = R_GetCurrentTexture(texture);
10122                 // scan ahead until we find a different texture
10123                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10124                 texturenumsurfaces = 0;
10125                 texturesurfacelist[texturenumsurfaces++] = surface;
10126                 if(FAKELIGHT_ENABLED)
10127                 {
10128                         rsurface.lightmaptexture = NULL;
10129                         rsurface.deluxemaptexture = NULL;
10130                         rsurface.uselightmaptexture = false;
10131                         for (;j < endsurface;j++)
10132                         {
10133                                 surface = rsurface.modelsurfaces + surfacelist[j];
10134                                 if (texture != surface->texture)
10135                                         break;
10136                                 texturesurfacelist[texturenumsurfaces++] = surface;
10137                         }
10138                 }
10139                 else
10140                 {
10141                         rsurface.lightmaptexture = surface->lightmaptexture;
10142                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10143                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10144                         for (;j < endsurface;j++)
10145                         {
10146                                 surface = rsurface.modelsurfaces + surfacelist[j];
10147                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10148                                         break;
10149                                 texturesurfacelist[texturenumsurfaces++] = surface;
10150                         }
10151                 }
10152                 // render the range of surfaces
10153                 if (ent == r_refdef.scene.worldentity)
10154                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10155                 else
10156                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10157         }
10158         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10159 }
10160
10161 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10162 {
10163         // transparent surfaces get pushed off into the transparent queue
10164         int surfacelistindex;
10165         const msurface_t *surface;
10166         vec3_t tempcenter, center;
10167         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10168         {
10169                 surface = texturesurfacelist[surfacelistindex];
10170                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10171                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10172                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10173                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10174                 if (queueentity->transparent_offset) // transparent offset
10175                 {
10176                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10177                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10178                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10179                 }
10180                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10181         }
10182 }
10183
10184 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10185 {
10186         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10187                 return;
10188         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10189                 return;
10190         RSurf_SetupDepthAndCulling();
10191         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10192         if (rsurface.batchvertex3fbuffer)
10193                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10194         else
10195                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10196         RSurf_DrawBatch();
10197 }
10198
10199 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10200 {
10201         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10202         CHECKGLERROR
10203         if (depthonly)
10204                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10205         else if (prepass)
10206         {
10207                 if (!rsurface.texture->currentnumlayers)
10208                         return;
10209                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10210                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10211                 else
10212                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10213         }
10214         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10215                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10216         else if (!rsurface.texture->currentnumlayers)
10217                 return;
10218         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10219         {
10220                 // in the deferred case, transparent surfaces were queued during prepass
10221                 if (!r_shadow_usingdeferredprepass)
10222                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10223         }
10224         else
10225         {
10226                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10227                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10228         }
10229         CHECKGLERROR
10230 }
10231
10232 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10233 {
10234         int i, j;
10235         texture_t *texture;
10236         R_FrameData_SetMark();
10237         // break the surface list down into batches by texture and use of lightmapping
10238         for (i = 0;i < numsurfaces;i = j)
10239         {
10240                 j = i + 1;
10241                 // texture is the base texture pointer, rsurface.texture is the
10242                 // current frame/skin the texture is directing us to use (for example
10243                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10244                 // use skin 1 instead)
10245                 texture = surfacelist[i]->texture;
10246                 rsurface.texture = R_GetCurrentTexture(texture);
10247                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10248                 {
10249                         // if this texture is not the kind we want, skip ahead to the next one
10250                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10251                                 ;
10252                         continue;
10253                 }
10254                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10255                 {
10256                         rsurface.lightmaptexture = NULL;
10257                         rsurface.deluxemaptexture = NULL;
10258                         rsurface.uselightmaptexture = false;
10259                         // simply scan ahead until we find a different texture or lightmap state
10260                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10261                                 ;
10262                 }
10263                 else
10264                 {
10265                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10266                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10267                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10268                         // simply scan ahead until we find a different texture or lightmap state
10269                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10270                                 ;
10271                 }
10272                 // render the range of surfaces
10273                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10274         }
10275         R_FrameData_ReturnToMark();
10276 }
10277
10278 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10279 {
10280         CHECKGLERROR
10281         if (depthonly)
10282                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10283         else if (prepass)
10284         {
10285                 if (!rsurface.texture->currentnumlayers)
10286                         return;
10287                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10288                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10289                 else
10290                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10291         }
10292         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10293                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10294         else if (!rsurface.texture->currentnumlayers)
10295                 return;
10296         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10297         {
10298                 // in the deferred case, transparent surfaces were queued during prepass
10299                 if (!r_shadow_usingdeferredprepass)
10300                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10301         }
10302         else
10303         {
10304                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10305                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10306         }
10307         CHECKGLERROR
10308 }
10309
10310 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10311 {
10312         int i, j;
10313         texture_t *texture;
10314         R_FrameData_SetMark();
10315         // break the surface list down into batches by texture and use of lightmapping
10316         for (i = 0;i < numsurfaces;i = j)
10317         {
10318                 j = i + 1;
10319                 // texture is the base texture pointer, rsurface.texture is the
10320                 // current frame/skin the texture is directing us to use (for example
10321                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10322                 // use skin 1 instead)
10323                 texture = surfacelist[i]->texture;
10324                 rsurface.texture = R_GetCurrentTexture(texture);
10325                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10326                 {
10327                         // if this texture is not the kind we want, skip ahead to the next one
10328                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10329                                 ;
10330                         continue;
10331                 }
10332                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10333                 {
10334                         rsurface.lightmaptexture = NULL;
10335                         rsurface.deluxemaptexture = NULL;
10336                         rsurface.uselightmaptexture = false;
10337                         // simply scan ahead until we find a different texture or lightmap state
10338                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10339                                 ;
10340                 }
10341                 else
10342                 {
10343                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10344                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10345                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10346                         // simply scan ahead until we find a different texture or lightmap state
10347                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10348                                 ;
10349                 }
10350                 // render the range of surfaces
10351                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10352         }
10353         R_FrameData_ReturnToMark();
10354 }
10355
10356 float locboxvertex3f[6*4*3] =
10357 {
10358         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10359         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10360         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10361         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10362         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10363         1,0,0, 0,0,0, 0,1,0, 1,1,0
10364 };
10365
10366 unsigned short locboxelements[6*2*3] =
10367 {
10368          0, 1, 2, 0, 2, 3,
10369          4, 5, 6, 4, 6, 7,
10370          8, 9,10, 8,10,11,
10371         12,13,14, 12,14,15,
10372         16,17,18, 16,18,19,
10373         20,21,22, 20,22,23
10374 };
10375
10376 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10377 {
10378         int i, j;
10379         cl_locnode_t *loc = (cl_locnode_t *)ent;
10380         vec3_t mins, size;
10381         float vertex3f[6*4*3];
10382         CHECKGLERROR
10383         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10384         GL_DepthMask(false);
10385         GL_DepthRange(0, 1);
10386         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10387         GL_DepthTest(true);
10388         GL_CullFace(GL_NONE);
10389         R_EntityMatrix(&identitymatrix);
10390
10391 //      R_Mesh_ResetTextureState();
10392
10393         i = surfacelist[0];
10394         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10395                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10396                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10397                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10398
10399         if (VectorCompare(loc->mins, loc->maxs))
10400         {
10401                 VectorSet(size, 2, 2, 2);
10402                 VectorMA(loc->mins, -0.5f, size, mins);
10403         }
10404         else
10405         {
10406                 VectorCopy(loc->mins, mins);
10407                 VectorSubtract(loc->maxs, loc->mins, size);
10408         }
10409
10410         for (i = 0;i < 6*4*3;)
10411                 for (j = 0;j < 3;j++, i++)
10412                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10413
10414         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10415         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10416         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10417 }
10418
10419 void R_DrawLocs(void)
10420 {
10421         int index;
10422         cl_locnode_t *loc, *nearestloc;
10423         vec3_t center;
10424         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10425         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10426         {
10427                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10428                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10429         }
10430 }
10431
10432 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10433 {
10434         if (decalsystem->decals)
10435                 Mem_Free(decalsystem->decals);
10436         memset(decalsystem, 0, sizeof(*decalsystem));
10437 }
10438
10439 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)
10440 {
10441         tridecal_t *decal;
10442         tridecal_t *decals;
10443         int i;
10444
10445         // expand or initialize the system
10446         if (decalsystem->maxdecals <= decalsystem->numdecals)
10447         {
10448                 decalsystem_t old = *decalsystem;
10449                 qboolean useshortelements;
10450                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10451                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10452                 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)));
10453                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10454                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10455                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10456                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10457                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10458                 if (decalsystem->numdecals)
10459                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10460                 if (old.decals)
10461                         Mem_Free(old.decals);
10462                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10463                         decalsystem->element3i[i] = i;
10464                 if (useshortelements)
10465                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10466                                 decalsystem->element3s[i] = i;
10467         }
10468
10469         // grab a decal and search for another free slot for the next one
10470         decals = decalsystem->decals;
10471         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10472         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10473                 ;
10474         decalsystem->freedecal = i;
10475         if (decalsystem->numdecals <= i)
10476                 decalsystem->numdecals = i + 1;
10477
10478         // initialize the decal
10479         decal->lived = 0;
10480         decal->triangleindex = triangleindex;
10481         decal->surfaceindex = surfaceindex;
10482         decal->decalsequence = decalsequence;
10483         decal->color4f[0][0] = c0[0];
10484         decal->color4f[0][1] = c0[1];
10485         decal->color4f[0][2] = c0[2];
10486         decal->color4f[0][3] = 1;
10487         decal->color4f[1][0] = c1[0];
10488         decal->color4f[1][1] = c1[1];
10489         decal->color4f[1][2] = c1[2];
10490         decal->color4f[1][3] = 1;
10491         decal->color4f[2][0] = c2[0];
10492         decal->color4f[2][1] = c2[1];
10493         decal->color4f[2][2] = c2[2];
10494         decal->color4f[2][3] = 1;
10495         decal->vertex3f[0][0] = v0[0];
10496         decal->vertex3f[0][1] = v0[1];
10497         decal->vertex3f[0][2] = v0[2];
10498         decal->vertex3f[1][0] = v1[0];
10499         decal->vertex3f[1][1] = v1[1];
10500         decal->vertex3f[1][2] = v1[2];
10501         decal->vertex3f[2][0] = v2[0];
10502         decal->vertex3f[2][1] = v2[1];
10503         decal->vertex3f[2][2] = v2[2];
10504         decal->texcoord2f[0][0] = t0[0];
10505         decal->texcoord2f[0][1] = t0[1];
10506         decal->texcoord2f[1][0] = t1[0];
10507         decal->texcoord2f[1][1] = t1[1];
10508         decal->texcoord2f[2][0] = t2[0];
10509         decal->texcoord2f[2][1] = t2[1];
10510         TriangleNormal(v0, v1, v2, decal->plane);
10511         VectorNormalize(decal->plane);
10512         decal->plane[3] = DotProduct(v0, decal->plane);
10513 }
10514
10515 extern cvar_t cl_decals_bias;
10516 extern cvar_t cl_decals_models;
10517 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10518 // baseparms, parms, temps
10519 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)
10520 {
10521         int cornerindex;
10522         int index;
10523         float v[9][3];
10524         const float *vertex3f;
10525         const float *normal3f;
10526         int numpoints;
10527         float points[2][9][3];
10528         float temp[3];
10529         float tc[9][2];
10530         float f;
10531         float c[9][4];
10532         const int *e;
10533
10534         e = rsurface.modelelement3i + 3*triangleindex;
10535
10536         vertex3f = rsurface.modelvertex3f;
10537         normal3f = rsurface.modelnormal3f;
10538
10539         if (normal3f)
10540         {
10541                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10542                 {
10543                         index = 3*e[cornerindex];
10544                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10545                 }
10546         }
10547         else
10548         {
10549                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10550                 {
10551                         index = 3*e[cornerindex];
10552                         VectorCopy(vertex3f + index, v[cornerindex]);
10553                 }
10554         }
10555
10556         // cull backfaces
10557         //TriangleNormal(v[0], v[1], v[2], normal);
10558         //if (DotProduct(normal, localnormal) < 0.0f)
10559         //      continue;
10560         // clip by each of the box planes formed from the projection matrix
10561         // if anything survives, we emit the decal
10562         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]);
10563         if (numpoints < 3)
10564                 return;
10565         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]);
10566         if (numpoints < 3)
10567                 return;
10568         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]);
10569         if (numpoints < 3)
10570                 return;
10571         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]);
10572         if (numpoints < 3)
10573                 return;
10574         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]);
10575         if (numpoints < 3)
10576                 return;
10577         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]);
10578         if (numpoints < 3)
10579                 return;
10580         // some part of the triangle survived, so we have to accept it...
10581         if (dynamic)
10582         {
10583                 // dynamic always uses the original triangle
10584                 numpoints = 3;
10585                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10586                 {
10587                         index = 3*e[cornerindex];
10588                         VectorCopy(vertex3f + index, v[cornerindex]);
10589                 }
10590         }
10591         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10592         {
10593                 // convert vertex positions to texcoords
10594                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10595                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10596                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10597                 // calculate distance fade from the projection origin
10598                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10599                 f = bound(0.0f, f, 1.0f);
10600                 c[cornerindex][0] = r * f;
10601                 c[cornerindex][1] = g * f;
10602                 c[cornerindex][2] = b * f;
10603                 c[cornerindex][3] = 1.0f;
10604                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10605         }
10606         if (dynamic)
10607                 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);
10608         else
10609                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10610                         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);
10611 }
10612 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)
10613 {
10614         matrix4x4_t projection;
10615         decalsystem_t *decalsystem;
10616         qboolean dynamic;
10617         dp_model_t *model;
10618         const msurface_t *surface;
10619         const msurface_t *surfaces;
10620         const int *surfacelist;
10621         const texture_t *texture;
10622         int numtriangles;
10623         int numsurfacelist;
10624         int surfacelistindex;
10625         int surfaceindex;
10626         int triangleindex;
10627         float localorigin[3];
10628         float localnormal[3];
10629         float localmins[3];
10630         float localmaxs[3];
10631         float localsize;
10632         //float normal[3];
10633         float planes[6][4];
10634         float angles[3];
10635         bih_t *bih;
10636         int bih_triangles_count;
10637         int bih_triangles[256];
10638         int bih_surfaces[256];
10639
10640         decalsystem = &ent->decalsystem;
10641         model = ent->model;
10642         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10643         {
10644                 R_DecalSystem_Reset(&ent->decalsystem);
10645                 return;
10646         }
10647
10648         if (!model->brush.data_leafs && !cl_decals_models.integer)
10649         {
10650                 if (decalsystem->model)
10651                         R_DecalSystem_Reset(decalsystem);
10652                 return;
10653         }
10654
10655         if (decalsystem->model != model)
10656                 R_DecalSystem_Reset(decalsystem);
10657         decalsystem->model = model;
10658
10659         RSurf_ActiveModelEntity(ent, true, false, false);
10660
10661         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10662         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10663         VectorNormalize(localnormal);
10664         localsize = worldsize*rsurface.inversematrixscale;
10665         localmins[0] = localorigin[0] - localsize;
10666         localmins[1] = localorigin[1] - localsize;
10667         localmins[2] = localorigin[2] - localsize;
10668         localmaxs[0] = localorigin[0] + localsize;
10669         localmaxs[1] = localorigin[1] + localsize;
10670         localmaxs[2] = localorigin[2] + localsize;
10671
10672         //VectorCopy(localnormal, planes[4]);
10673         //VectorVectors(planes[4], planes[2], planes[0]);
10674         AnglesFromVectors(angles, localnormal, NULL, false);
10675         AngleVectors(angles, planes[0], planes[2], planes[4]);
10676         VectorNegate(planes[0], planes[1]);
10677         VectorNegate(planes[2], planes[3]);
10678         VectorNegate(planes[4], planes[5]);
10679         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10680         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10681         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10682         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10683         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10684         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10685
10686 #if 1
10687 // works
10688 {
10689         matrix4x4_t forwardprojection;
10690         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10691         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10692 }
10693 #else
10694 // broken
10695 {
10696         float projectionvector[4][3];
10697         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10698         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10699         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10700         projectionvector[0][0] = planes[0][0] * ilocalsize;
10701         projectionvector[0][1] = planes[1][0] * ilocalsize;
10702         projectionvector[0][2] = planes[2][0] * ilocalsize;
10703         projectionvector[1][0] = planes[0][1] * ilocalsize;
10704         projectionvector[1][1] = planes[1][1] * ilocalsize;
10705         projectionvector[1][2] = planes[2][1] * ilocalsize;
10706         projectionvector[2][0] = planes[0][2] * ilocalsize;
10707         projectionvector[2][1] = planes[1][2] * ilocalsize;
10708         projectionvector[2][2] = planes[2][2] * ilocalsize;
10709         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10710         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10711         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10712         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10713 }
10714 #endif
10715
10716         dynamic = model->surfmesh.isanimated;
10717         numsurfacelist = model->nummodelsurfaces;
10718         surfacelist = model->sortedmodelsurfaces;
10719         surfaces = model->data_surfaces;
10720
10721         bih = NULL;
10722         bih_triangles_count = -1;
10723         if(!dynamic)
10724         {
10725                 if(model->render_bih.numleafs)
10726                         bih = &model->render_bih;
10727                 else if(model->collision_bih.numleafs)
10728                         bih = &model->collision_bih;
10729         }
10730         if(bih)
10731                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10732         if(bih_triangles_count == 0)
10733                 return;
10734         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10735                 return;
10736         if(bih_triangles_count > 0)
10737         {
10738                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10739                 {
10740                         surfaceindex = bih_surfaces[triangleindex];
10741                         surface = surfaces + surfaceindex;
10742                         texture = surface->texture;
10743                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10744                                 continue;
10745                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10746                                 continue;
10747                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10748                 }
10749         }
10750         else
10751         {
10752                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10753                 {
10754                         surfaceindex = surfacelist[surfacelistindex];
10755                         surface = surfaces + surfaceindex;
10756                         // check cull box first because it rejects more than any other check
10757                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10758                                 continue;
10759                         // skip transparent surfaces
10760                         texture = surface->texture;
10761                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10762                                 continue;
10763                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10764                                 continue;
10765                         numtriangles = surface->num_triangles;
10766                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10767                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10768                 }
10769         }
10770 }
10771
10772 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10773 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)
10774 {
10775         int renderentityindex;
10776         float worldmins[3];
10777         float worldmaxs[3];
10778         entity_render_t *ent;
10779
10780         if (!cl_decals_newsystem.integer)
10781                 return;
10782
10783         worldmins[0] = worldorigin[0] - worldsize;
10784         worldmins[1] = worldorigin[1] - worldsize;
10785         worldmins[2] = worldorigin[2] - worldsize;
10786         worldmaxs[0] = worldorigin[0] + worldsize;
10787         worldmaxs[1] = worldorigin[1] + worldsize;
10788         worldmaxs[2] = worldorigin[2] + worldsize;
10789
10790         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10791
10792         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10793         {
10794                 ent = r_refdef.scene.entities[renderentityindex];
10795                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10796                         continue;
10797
10798                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10799         }
10800 }
10801
10802 typedef struct r_decalsystem_splatqueue_s
10803 {
10804         vec3_t worldorigin;
10805         vec3_t worldnormal;
10806         float color[4];
10807         float tcrange[4];
10808         float worldsize;
10809         int decalsequence;
10810 }
10811 r_decalsystem_splatqueue_t;
10812
10813 int r_decalsystem_numqueued = 0;
10814 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10815
10816 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)
10817 {
10818         r_decalsystem_splatqueue_t *queue;
10819
10820         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10821                 return;
10822
10823         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10824         VectorCopy(worldorigin, queue->worldorigin);
10825         VectorCopy(worldnormal, queue->worldnormal);
10826         Vector4Set(queue->color, r, g, b, a);
10827         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10828         queue->worldsize = worldsize;
10829         queue->decalsequence = cl.decalsequence++;
10830 }
10831
10832 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10833 {
10834         int i;
10835         r_decalsystem_splatqueue_t *queue;
10836
10837         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10838                 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);
10839         r_decalsystem_numqueued = 0;
10840 }
10841
10842 extern cvar_t cl_decals_max;
10843 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10844 {
10845         int i;
10846         decalsystem_t *decalsystem = &ent->decalsystem;
10847         int numdecals;
10848         int killsequence;
10849         tridecal_t *decal;
10850         float frametime;
10851         float lifetime;
10852
10853         if (!decalsystem->numdecals)
10854                 return;
10855
10856         if (r_showsurfaces.integer)
10857                 return;
10858
10859         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10860         {
10861                 R_DecalSystem_Reset(decalsystem);
10862                 return;
10863         }
10864
10865         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10866         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10867
10868         if (decalsystem->lastupdatetime)
10869                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10870         else
10871                 frametime = 0;
10872         decalsystem->lastupdatetime = r_refdef.scene.time;
10873         decal = decalsystem->decals;
10874         numdecals = decalsystem->numdecals;
10875
10876         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10877         {
10878                 if (decal->color4f[0][3])
10879                 {
10880                         decal->lived += frametime;
10881                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10882                         {
10883                                 memset(decal, 0, sizeof(*decal));
10884                                 if (decalsystem->freedecal > i)
10885                                         decalsystem->freedecal = i;
10886                         }
10887                 }
10888         }
10889         decal = decalsystem->decals;
10890         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10891                 numdecals--;
10892
10893         // collapse the array by shuffling the tail decals into the gaps
10894         for (;;)
10895         {
10896                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10897                         decalsystem->freedecal++;
10898                 if (decalsystem->freedecal == numdecals)
10899                         break;
10900                 decal[decalsystem->freedecal] = decal[--numdecals];
10901         }
10902
10903         decalsystem->numdecals = numdecals;
10904
10905         if (numdecals <= 0)
10906         {
10907                 // if there are no decals left, reset decalsystem
10908                 R_DecalSystem_Reset(decalsystem);
10909         }
10910 }
10911
10912 extern skinframe_t *decalskinframe;
10913 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10914 {
10915         int i;
10916         decalsystem_t *decalsystem = &ent->decalsystem;
10917         int numdecals;
10918         tridecal_t *decal;
10919         float faderate;
10920         float alpha;
10921         float *v3f;
10922         float *c4f;
10923         float *t2f;
10924         const int *e;
10925         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10926         int numtris = 0;
10927
10928         numdecals = decalsystem->numdecals;
10929         if (!numdecals)
10930                 return;
10931
10932         if (r_showsurfaces.integer)
10933                 return;
10934
10935         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10936         {
10937                 R_DecalSystem_Reset(decalsystem);
10938                 return;
10939         }
10940
10941         // if the model is static it doesn't matter what value we give for
10942         // wantnormals and wanttangents, so this logic uses only rules applicable
10943         // to a model, knowing that they are meaningless otherwise
10944         if (ent == r_refdef.scene.worldentity)
10945                 RSurf_ActiveWorldEntity();
10946         else
10947                 RSurf_ActiveModelEntity(ent, false, false, false);
10948
10949         decalsystem->lastupdatetime = r_refdef.scene.time;
10950         decal = decalsystem->decals;
10951
10952         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10953
10954         // update vertex positions for animated models
10955         v3f = decalsystem->vertex3f;
10956         c4f = decalsystem->color4f;
10957         t2f = decalsystem->texcoord2f;
10958         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10959         {
10960                 if (!decal->color4f[0][3])
10961                         continue;
10962
10963                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10964                         continue;
10965
10966                 // skip backfaces
10967                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10968                         continue;
10969
10970                 // update color values for fading decals
10971                 if (decal->lived >= cl_decals_time.value)
10972                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10973                 else
10974                         alpha = 1.0f;
10975
10976                 c4f[ 0] = decal->color4f[0][0] * alpha;
10977                 c4f[ 1] = decal->color4f[0][1] * alpha;
10978                 c4f[ 2] = decal->color4f[0][2] * alpha;
10979                 c4f[ 3] = 1;
10980                 c4f[ 4] = decal->color4f[1][0] * alpha;
10981                 c4f[ 5] = decal->color4f[1][1] * alpha;
10982                 c4f[ 6] = decal->color4f[1][2] * alpha;
10983                 c4f[ 7] = 1;
10984                 c4f[ 8] = decal->color4f[2][0] * alpha;
10985                 c4f[ 9] = decal->color4f[2][1] * alpha;
10986                 c4f[10] = decal->color4f[2][2] * alpha;
10987                 c4f[11] = 1;
10988
10989                 t2f[0] = decal->texcoord2f[0][0];
10990                 t2f[1] = decal->texcoord2f[0][1];
10991                 t2f[2] = decal->texcoord2f[1][0];
10992                 t2f[3] = decal->texcoord2f[1][1];
10993                 t2f[4] = decal->texcoord2f[2][0];
10994                 t2f[5] = decal->texcoord2f[2][1];
10995
10996                 // update vertex positions for animated models
10997                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10998                 {
10999                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11000                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11001                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11002                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11003                 }
11004                 else
11005                 {
11006                         VectorCopy(decal->vertex3f[0], v3f);
11007                         VectorCopy(decal->vertex3f[1], v3f + 3);
11008                         VectorCopy(decal->vertex3f[2], v3f + 6);
11009                 }
11010
11011                 if (r_refdef.fogenabled)
11012                 {
11013                         alpha = RSurf_FogVertex(v3f);
11014                         VectorScale(c4f, alpha, c4f);
11015                         alpha = RSurf_FogVertex(v3f + 3);
11016                         VectorScale(c4f + 4, alpha, c4f + 4);
11017                         alpha = RSurf_FogVertex(v3f + 6);
11018                         VectorScale(c4f + 8, alpha, c4f + 8);
11019                 }
11020
11021                 v3f += 9;
11022                 c4f += 12;
11023                 t2f += 6;
11024                 numtris++;
11025         }
11026
11027         if (numtris > 0)
11028         {
11029                 r_refdef.stats.drawndecals += numtris;
11030
11031                 // now render the decals all at once
11032                 // (this assumes they all use one particle font texture!)
11033                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11034 //              R_Mesh_ResetTextureState();
11035                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11036                 GL_DepthMask(false);
11037                 GL_DepthRange(0, 1);
11038                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11039                 GL_DepthTest(true);
11040                 GL_CullFace(GL_NONE);
11041                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11042                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11043                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11044         }
11045 }
11046
11047 static void R_DrawModelDecals(void)
11048 {
11049         int i, numdecals;
11050
11051         // fade faster when there are too many decals
11052         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11053         for (i = 0;i < r_refdef.scene.numentities;i++)
11054                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11055
11056         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11057         for (i = 0;i < r_refdef.scene.numentities;i++)
11058                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11059                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11060
11061         R_DecalSystem_ApplySplatEntitiesQueue();
11062
11063         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11064         for (i = 0;i < r_refdef.scene.numentities;i++)
11065                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11066
11067         r_refdef.stats.totaldecals += numdecals;
11068
11069         if (r_showsurfaces.integer)
11070                 return;
11071
11072         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11073
11074         for (i = 0;i < r_refdef.scene.numentities;i++)
11075         {
11076                 if (!r_refdef.viewcache.entityvisible[i])
11077                         continue;
11078                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11079                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11080         }
11081 }
11082
11083 extern cvar_t mod_collision_bih;
11084 void R_DrawDebugModel(void)
11085 {
11086         entity_render_t *ent = rsurface.entity;
11087         int i, j, k, l, flagsmask;
11088         const msurface_t *surface;
11089         dp_model_t *model = ent->model;
11090         vec3_t v;
11091
11092         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11093                 return;
11094
11095         if (r_showoverdraw.value > 0)
11096         {
11097                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11098                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11099                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11100                 GL_DepthTest(false);
11101                 GL_DepthMask(false);
11102                 GL_DepthRange(0, 1);
11103                 GL_BlendFunc(GL_ONE, GL_ONE);
11104                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11105                 {
11106                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11107                                 continue;
11108                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11109                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11110                         {
11111                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11112                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11113                                 if (!rsurface.texture->currentlayers->depthmask)
11114                                         GL_Color(c, 0, 0, 1.0f);
11115                                 else if (ent == r_refdef.scene.worldentity)
11116                                         GL_Color(c, c, c, 1.0f);
11117                                 else
11118                                         GL_Color(0, c, 0, 1.0f);
11119                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11120                                 RSurf_DrawBatch();
11121                         }
11122                 }
11123                 rsurface.texture = NULL;
11124         }
11125
11126         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11127
11128 //      R_Mesh_ResetTextureState();
11129         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11130         GL_DepthRange(0, 1);
11131         GL_DepthTest(!r_showdisabledepthtest.integer);
11132         GL_DepthMask(false);
11133         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11134
11135         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11136         {
11137                 int triangleindex;
11138                 int bihleafindex;
11139                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11140                 const q3mbrush_t *brush;
11141                 const bih_t *bih = &model->collision_bih;
11142                 const bih_leaf_t *bihleaf;
11143                 float vertex3f[3][3];
11144                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11145                 cullbox = false;
11146                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11147                 {
11148                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11149                                 continue;
11150                         switch (bihleaf->type)
11151                         {
11152                         case BIH_BRUSH:
11153                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11154                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11155                                 {
11156                                         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);
11157                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11158                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11159                                 }
11160                                 break;
11161                         case BIH_COLLISIONTRIANGLE:
11162                                 triangleindex = bihleaf->itemindex;
11163                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11164                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11165                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11166                                 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);
11167                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11168                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11169                                 break;
11170                         case BIH_RENDERTRIANGLE:
11171                                 triangleindex = bihleaf->itemindex;
11172                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11173                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11174                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11175                                 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);
11176                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11177                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11178                                 break;
11179                         }
11180                 }
11181         }
11182
11183         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11184
11185         if (r_showtris.integer && qglPolygonMode)
11186         {
11187                 if (r_showdisabledepthtest.integer)
11188                 {
11189                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11190                         GL_DepthMask(false);
11191                 }
11192                 else
11193                 {
11194                         GL_BlendFunc(GL_ONE, GL_ZERO);
11195                         GL_DepthMask(true);
11196                 }
11197                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11198                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11199                 {
11200                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11201                                 continue;
11202                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11203                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11204                         {
11205                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11206                                 if (!rsurface.texture->currentlayers->depthmask)
11207                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11208                                 else if (ent == r_refdef.scene.worldentity)
11209                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11210                                 else
11211                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11212                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11213                                 RSurf_DrawBatch();
11214                         }
11215                 }
11216                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11217                 rsurface.texture = NULL;
11218         }
11219
11220         if (r_shownormals.value != 0 && qglBegin)
11221         {
11222                 if (r_showdisabledepthtest.integer)
11223                 {
11224                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11225                         GL_DepthMask(false);
11226                 }
11227                 else
11228                 {
11229                         GL_BlendFunc(GL_ONE, GL_ZERO);
11230                         GL_DepthMask(true);
11231                 }
11232                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11233                 {
11234                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11235                                 continue;
11236                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11237                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11238                         {
11239                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11240                                 qglBegin(GL_LINES);
11241                                 if (r_shownormals.value < 0)
11242                                 {
11243                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11244                                         {
11245                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11246                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11247                                                 qglVertex3f(v[0], v[1], v[2]);
11248                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11249                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11250                                                 qglVertex3f(v[0], v[1], v[2]);
11251                                         }
11252                                 }
11253                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11254                                 {
11255                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11256                                         {
11257                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11258                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11259                                                 qglVertex3f(v[0], v[1], v[2]);
11260                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + 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                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11265                                         {
11266                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11267                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11268                                                 qglVertex3f(v[0], v[1], v[2]);
11269                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11270                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11271                                                 qglVertex3f(v[0], v[1], v[2]);
11272                                         }
11273                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11274                                         {
11275                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11276                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11277                                                 qglVertex3f(v[0], v[1], v[2]);
11278                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11279                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11280                                                 qglVertex3f(v[0], v[1], v[2]);
11281                                         }
11282                                 }
11283                                 qglEnd();
11284                                 CHECKGLERROR
11285                         }
11286                 }
11287                 rsurface.texture = NULL;
11288         }
11289 }
11290
11291 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11292 int r_maxsurfacelist = 0;
11293 const msurface_t **r_surfacelist = NULL;
11294 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11295 {
11296         int i, j, endj, flagsmask;
11297         dp_model_t *model = r_refdef.scene.worldmodel;
11298         msurface_t *surfaces;
11299         unsigned char *update;
11300         int numsurfacelist = 0;
11301         if (model == NULL)
11302                 return;
11303
11304         if (r_maxsurfacelist < model->num_surfaces)
11305         {
11306                 r_maxsurfacelist = model->num_surfaces;
11307                 if (r_surfacelist)
11308                         Mem_Free((msurface_t**)r_surfacelist);
11309                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11310         }
11311
11312         RSurf_ActiveWorldEntity();
11313
11314         surfaces = model->data_surfaces;
11315         update = model->brushq1.lightmapupdateflags;
11316
11317         // update light styles on this submodel
11318         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11319         {
11320                 model_brush_lightstyleinfo_t *style;
11321                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11322                 {
11323                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11324                         {
11325                                 int *list = style->surfacelist;
11326                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11327                                 for (j = 0;j < style->numsurfaces;j++)
11328                                         update[list[j]] = true;
11329                         }
11330                 }
11331         }
11332
11333         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11334
11335         if (debug)
11336         {
11337                 R_DrawDebugModel();
11338                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11339                 return;
11340         }
11341
11342         rsurface.lightmaptexture = NULL;
11343         rsurface.deluxemaptexture = NULL;
11344         rsurface.uselightmaptexture = false;
11345         rsurface.texture = NULL;
11346         rsurface.rtlight = NULL;
11347         numsurfacelist = 0;
11348         // add visible surfaces to draw list
11349         for (i = 0;i < model->nummodelsurfaces;i++)
11350         {
11351                 j = model->sortedmodelsurfaces[i];
11352                 if (r_refdef.viewcache.world_surfacevisible[j])
11353                         r_surfacelist[numsurfacelist++] = surfaces + j;
11354         }
11355         // update lightmaps if needed
11356         if (model->brushq1.firstrender)
11357         {
11358                 model->brushq1.firstrender = false;
11359                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11360                         if (update[j])
11361                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11362         }
11363         else if (update)
11364         {
11365                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11366                         if (r_refdef.viewcache.world_surfacevisible[j])
11367                                 if (update[j])
11368                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11369         }
11370         // don't do anything if there were no surfaces
11371         if (!numsurfacelist)
11372         {
11373                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11374                 return;
11375         }
11376         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11377
11378         // add to stats if desired
11379         if (r_speeds.integer && !skysurfaces && !depthonly)
11380         {
11381                 r_refdef.stats.world_surfaces += numsurfacelist;
11382                 for (j = 0;j < numsurfacelist;j++)
11383                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11384         }
11385
11386         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11387 }
11388
11389 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11390 {
11391         int i, j, endj, flagsmask;
11392         dp_model_t *model = ent->model;
11393         msurface_t *surfaces;
11394         unsigned char *update;
11395         int numsurfacelist = 0;
11396         if (model == NULL)
11397                 return;
11398
11399         if (r_maxsurfacelist < model->num_surfaces)
11400         {
11401                 r_maxsurfacelist = model->num_surfaces;
11402                 if (r_surfacelist)
11403                         Mem_Free((msurface_t **)r_surfacelist);
11404                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11405         }
11406
11407         // if the model is static it doesn't matter what value we give for
11408         // wantnormals and wanttangents, so this logic uses only rules applicable
11409         // to a model, knowing that they are meaningless otherwise
11410         if (ent == r_refdef.scene.worldentity)
11411                 RSurf_ActiveWorldEntity();
11412         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11413                 RSurf_ActiveModelEntity(ent, false, false, false);
11414         else if (prepass)
11415                 RSurf_ActiveModelEntity(ent, true, true, true);
11416         else if (depthonly)
11417         {
11418                 switch (vid.renderpath)
11419                 {
11420                 case RENDERPATH_GL20:
11421                 case RENDERPATH_D3D9:
11422                 case RENDERPATH_D3D10:
11423                 case RENDERPATH_D3D11:
11424                 case RENDERPATH_SOFT:
11425                 case RENDERPATH_GLES2:
11426                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11427                         break;
11428                 case RENDERPATH_GL11:
11429                 case RENDERPATH_GL13:
11430                 case RENDERPATH_GLES1:
11431                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11432                         break;
11433                 }
11434         }
11435         else
11436         {
11437                 switch (vid.renderpath)
11438                 {
11439                 case RENDERPATH_GL20:
11440                 case RENDERPATH_D3D9:
11441                 case RENDERPATH_D3D10:
11442                 case RENDERPATH_D3D11:
11443                 case RENDERPATH_SOFT:
11444                 case RENDERPATH_GLES2:
11445                         RSurf_ActiveModelEntity(ent, true, true, false);
11446                         break;
11447                 case RENDERPATH_GL11:
11448                 case RENDERPATH_GL13:
11449                 case RENDERPATH_GLES1:
11450                         RSurf_ActiveModelEntity(ent, true, false, false);
11451                         break;
11452                 }
11453         }
11454
11455         surfaces = model->data_surfaces;
11456         update = model->brushq1.lightmapupdateflags;
11457
11458         // update light styles
11459         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11460         {
11461                 model_brush_lightstyleinfo_t *style;
11462                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11463                 {
11464                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11465                         {
11466                                 int *list = style->surfacelist;
11467                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11468                                 for (j = 0;j < style->numsurfaces;j++)
11469                                         update[list[j]] = true;
11470                         }
11471                 }
11472         }
11473
11474         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11475
11476         if (debug)
11477         {
11478                 R_DrawDebugModel();
11479                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11480                 return;
11481         }
11482
11483         rsurface.lightmaptexture = NULL;
11484         rsurface.deluxemaptexture = NULL;
11485         rsurface.uselightmaptexture = false;
11486         rsurface.texture = NULL;
11487         rsurface.rtlight = NULL;
11488         numsurfacelist = 0;
11489         // add visible surfaces to draw list
11490         for (i = 0;i < model->nummodelsurfaces;i++)
11491                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11492         // don't do anything if there were no surfaces
11493         if (!numsurfacelist)
11494         {
11495                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11496                 return;
11497         }
11498         // update lightmaps if needed
11499         if (update)
11500         {
11501                 int updated = 0;
11502                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11503                 {
11504                         if (update[j])
11505                         {
11506                                 updated++;
11507                                 R_BuildLightMap(ent, surfaces + j);
11508                         }
11509                 }
11510         }
11511         if (update)
11512                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11513                         if (update[j])
11514                                 R_BuildLightMap(ent, surfaces + j);
11515         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11516
11517         // add to stats if desired
11518         if (r_speeds.integer && !skysurfaces && !depthonly)
11519         {
11520                 r_refdef.stats.entities_surfaces += numsurfacelist;
11521                 for (j = 0;j < numsurfacelist;j++)
11522                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11523         }
11524
11525         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11526 }
11527
11528 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11529 {
11530         static texture_t texture;
11531         static msurface_t surface;
11532         const msurface_t *surfacelist = &surface;
11533
11534         // fake enough texture and surface state to render this geometry
11535
11536         texture.update_lastrenderframe = -1; // regenerate this texture
11537         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11538         texture.currentskinframe = skinframe;
11539         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11540         texture.offsetmapping = OFFSETMAPPING_OFF;
11541         texture.offsetscale = 1;
11542         texture.specularscalemod = 1;
11543         texture.specularpowermod = 1;
11544
11545         surface.texture = &texture;
11546         surface.num_triangles = numtriangles;
11547         surface.num_firsttriangle = firsttriangle;
11548         surface.num_vertices = numvertices;
11549         surface.num_firstvertex = firstvertex;
11550
11551         // now render it
11552         rsurface.texture = R_GetCurrentTexture(surface.texture);
11553         rsurface.lightmaptexture = NULL;
11554         rsurface.deluxemaptexture = NULL;
11555         rsurface.uselightmaptexture = false;
11556         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11557 }
11558
11559 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)
11560 {
11561         static msurface_t surface;
11562         const msurface_t *surfacelist = &surface;
11563
11564         // fake enough texture and surface state to render this geometry
11565         surface.texture = texture;
11566         surface.num_triangles = numtriangles;
11567         surface.num_firsttriangle = firsttriangle;
11568         surface.num_vertices = numvertices;
11569         surface.num_firstvertex = firstvertex;
11570
11571         // now render it
11572         rsurface.texture = R_GetCurrentTexture(surface.texture);
11573         rsurface.lightmaptexture = NULL;
11574         rsurface.deluxemaptexture = NULL;
11575         rsurface.uselightmaptexture = false;
11576         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11577 }