]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
OpenGL 2.0 path: Make handling of Alpha-To-Coverage same as AlphaTest (enabling befor...
[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
177 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
178 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
179 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
180 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
181
182 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
183 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
184 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
185 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
186 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
187 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
188 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
189
190 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
191 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
192 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
193 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)"};
194 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
195 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
196 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
197 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
199 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
200
201 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"};
202
203 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"};
204
205 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
206
207 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
208 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
209 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
210 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
211 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
212 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
213 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
214 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
215 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
216
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 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"};
219
220 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."};
221
222 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)"};
223
224 extern cvar_t v_glslgamma;
225
226 extern qboolean v_flipped_state;
227
228 static struct r_bloomstate_s
229 {
230         qboolean enabled;
231         qboolean hdr;
232
233         int bloomwidth, bloomheight;
234
235         textype_t texturetype;
236         int viewfbo; // used to check if r_viewfbo cvar has changed
237
238         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241
242         int screentexturewidth, screentextureheight;
243         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244
245         int bloomtexturewidth, bloomtextureheight;
246         rtexture_t *texture_bloom;
247
248         // arrays for rendering the screen passes
249         float screentexcoord2f[8];
250         float bloomtexcoord2f[8];
251         float offsettexcoord2f[8];
252
253         r_viewport_t viewport;
254 }
255 r_bloomstate;
256
257 r_waterstate_t r_waterstate;
258
259 /// shadow volume bsp struct with automatically growing nodes buffer
260 svbsp_t r_svbsp;
261
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
275
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
278 {
279         char basename[64];
280         rtexture_t *texture;
281 }
282 cubemapinfo_t;
283
284 int r_texture_numcubemaps;
285 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
286
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
290
291 typedef struct r_qwskincache_s
292 {
293         char name[MAX_QPATH];
294         skinframe_t *skinframe;
295 }
296 r_qwskincache_t;
297
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
300
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
305 {
306         0, 0, 0,
307         1, 0, 0,
308         1, 1, 0,
309         0, 1, 0
310 };
311 const float r_d3dscreenvertex3f[12] =
312 {
313         0, 1, 0,
314         1, 1, 0,
315         1, 0, 0,
316         0, 0, 0
317 };
318
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = in[0] * r;
325                 out[1] = in[1] * g;
326                 out[2] = in[2] * b;
327                 out[3] = in[3];
328                 in += 4;
329                 out += 4;
330         }
331 }
332
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = r;
339                 out[1] = g;
340                 out[2] = b;
341                 out[3] = a;
342                 out += 4;
343         }
344 }
345
346 // FIXME: move this to client?
347 void FOG_clear(void)
348 {
349         if (gamemode == GAME_NEHAHRA)
350         {
351                 Cvar_Set("gl_fogenable", "0");
352                 Cvar_Set("gl_fogdensity", "0.2");
353                 Cvar_Set("gl_fogred", "0.3");
354                 Cvar_Set("gl_foggreen", "0.3");
355                 Cvar_Set("gl_fogblue", "0.3");
356         }
357         r_refdef.fog_density = 0;
358         r_refdef.fog_red = 0;
359         r_refdef.fog_green = 0;
360         r_refdef.fog_blue = 0;
361         r_refdef.fog_alpha = 1;
362         r_refdef.fog_start = 0;
363         r_refdef.fog_end = 16384;
364         r_refdef.fog_height = 1<<30;
365         r_refdef.fog_fadedepth = 128;
366         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 }
368
369 static void R_BuildBlankTextures(void)
370 {
371         unsigned char data[4];
372         data[2] = 128; // normal X
373         data[1] = 128; // normal Y
374         data[0] = 255; // normal Z
375         data[3] = 128; // height
376         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377         data[0] = 255;
378         data[1] = 255;
379         data[2] = 255;
380         data[3] = 255;
381         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 128;
383         data[1] = 128;
384         data[2] = 128;
385         data[3] = 255;
386         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 0;
388         data[1] = 0;
389         data[2] = 0;
390         data[3] = 255;
391         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNoTexture(void)
395 {
396         int x, y;
397         unsigned char pix[16][16][4];
398         // this makes a light grey/dark grey checkerboard texture
399         for (y = 0;y < 16;y++)
400         {
401                 for (x = 0;x < 16;x++)
402                 {
403                         if ((y < 8) ^ (x < 8))
404                         {
405                                 pix[y][x][0] = 128;
406                                 pix[y][x][1] = 128;
407                                 pix[y][x][2] = 128;
408                                 pix[y][x][3] = 255;
409                         }
410                         else
411                         {
412                                 pix[y][x][0] = 64;
413                                 pix[y][x][1] = 64;
414                                 pix[y][x][2] = 64;
415                                 pix[y][x][3] = 255;
416                         }
417                 }
418         }
419         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildWhiteCube(void)
423 {
424         unsigned char data[6*1*1*4];
425         memset(data, 255, sizeof(data));
426         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildNormalizationCube(void)
430 {
431         int x, y, side;
432         vec3_t v;
433         vec_t s, t, intensity;
434 #define NORMSIZE 64
435         unsigned char *data;
436         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437         for (side = 0;side < 6;side++)
438         {
439                 for (y = 0;y < NORMSIZE;y++)
440                 {
441                         for (x = 0;x < NORMSIZE;x++)
442                         {
443                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 switch(side)
446                                 {
447                                 default:
448                                 case 0:
449                                         v[0] = 1;
450                                         v[1] = -t;
451                                         v[2] = -s;
452                                         break;
453                                 case 1:
454                                         v[0] = -1;
455                                         v[1] = -t;
456                                         v[2] = s;
457                                         break;
458                                 case 2:
459                                         v[0] = s;
460                                         v[1] = 1;
461                                         v[2] = t;
462                                         break;
463                                 case 3:
464                                         v[0] = s;
465                                         v[1] = -1;
466                                         v[2] = -t;
467                                         break;
468                                 case 4:
469                                         v[0] = s;
470                                         v[1] = -t;
471                                         v[2] = 1;
472                                         break;
473                                 case 5:
474                                         v[0] = -s;
475                                         v[1] = -t;
476                                         v[2] = -1;
477                                         break;
478                                 }
479                                 intensity = 127.0f / sqrt(DotProduct(v, v));
480                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483                                 data[((side*64+y)*64+x)*4+3] = 255;
484                         }
485                 }
486         }
487         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
488         Mem_Free(data);
489 }
490
491 static void R_BuildFogTexture(void)
492 {
493         int x, b;
494 #define FOGWIDTH 256
495         unsigned char data1[FOGWIDTH][4];
496         //unsigned char data2[FOGWIDTH][4];
497         double d, r, alpha;
498
499         r_refdef.fogmasktable_start = r_refdef.fog_start;
500         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501         r_refdef.fogmasktable_range = r_refdef.fogrange;
502         r_refdef.fogmasktable_density = r_refdef.fog_density;
503
504         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506         {
507                 d = (x * r - r_refdef.fogmasktable_start);
508                 if(developer_extra.integer)
509                         Con_DPrintf("%f ", d);
510                 d = max(0, d);
511                 if (r_fog_exp2.integer)
512                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513                 else
514                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515                 if(developer_extra.integer)
516                         Con_DPrintf(" : %f ", alpha);
517                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518                 if(developer_extra.integer)
519                         Con_DPrintf(" = %f\n", alpha);
520                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521         }
522
523         for (x = 0;x < FOGWIDTH;x++)
524         {
525                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
526                 data1[x][0] = b;
527                 data1[x][1] = b;
528                 data1[x][2] = b;
529                 data1[x][3] = 255;
530                 //data2[x][0] = 255 - b;
531                 //data2[x][1] = 255 - b;
532                 //data2[x][2] = 255 - b;
533                 //data2[x][3] = 255;
534         }
535         if (r_texture_fogattenuation)
536         {
537                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539         }
540         else
541         {
542                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
544         }
545 }
546
547 static void R_BuildFogHeightTexture(void)
548 {
549         unsigned char *inpixels;
550         int size;
551         int x;
552         int y;
553         int j;
554         float c[4];
555         float f;
556         inpixels = NULL;
557         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558         if (r_refdef.fogheighttexturename[0])
559                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560         if (!inpixels)
561         {
562                 r_refdef.fog_height_tablesize = 0;
563                 if (r_texture_fogheighttexture)
564                         R_FreeTexture(r_texture_fogheighttexture);
565                 r_texture_fogheighttexture = NULL;
566                 if (r_refdef.fog_height_table2d)
567                         Mem_Free(r_refdef.fog_height_table2d);
568                 r_refdef.fog_height_table2d = NULL;
569                 if (r_refdef.fog_height_table1d)
570                         Mem_Free(r_refdef.fog_height_table1d);
571                 r_refdef.fog_height_table1d = NULL;
572                 return;
573         }
574         size = image_width;
575         r_refdef.fog_height_tablesize = size;
576         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579         Mem_Free(inpixels);
580         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
581         // average fog color table accounting for every fog layer between a point
582         // and the camera.  (Note: attenuation is handled separately!)
583         for (y = 0;y < size;y++)
584         {
585                 for (x = 0;x < size;x++)
586                 {
587                         Vector4Clear(c);
588                         f = 0;
589                         if (x < y)
590                         {
591                                 for (j = x;j <= y;j++)
592                                 {
593                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594                                         f++;
595                                 }
596                         }
597                         else
598                         {
599                                 for (j = x;j >= y;j--)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         f = 1.0f / f;
606                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610                 }
611         }
612         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 }
614
615 //=======================================================================================================================================================
616
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
619 ;
620
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
623 ;
624
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
627
628 //=======================================================================================================================================================
629
630 typedef struct shaderpermutationinfo_s
631 {
632         const char *pretext;
633         const char *name;
634 }
635 shaderpermutationinfo_t;
636
637 typedef struct shadermodeinfo_s
638 {
639         const char *vertexfilename;
640         const char *geometryfilename;
641         const char *fragmentfilename;
642         const char *pretext;
643         const char *name;
644 }
645 shadermodeinfo_t;
646
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {
650         {"#define USEDIFFUSE\n", " diffuse"},
651         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652         {"#define USEVIEWTINT\n", " viewtint"},
653         {"#define USECOLORMAPPING\n", " colormapping"},
654         {"#define USESATURATION\n", " saturation"},
655         {"#define USEFOGINSIDE\n", " foginside"},
656         {"#define USEFOGOUTSIDE\n", " fogoutside"},
657         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659         {"#define USEGAMMARAMPS\n", " gammaramps"},
660         {"#define USECUBEFILTER\n", " cubefilter"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEBLOOM\n", " bloom"},
663         {"#define USESPECULAR\n", " specular"},
664         {"#define USEPOSTPROCESSING\n", " postprocessing"},
665         {"#define USEREFLECTION\n", " reflection"},
666         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675         {"#define USEALPHAKILL\n", " alphakill"},
676         {"#define USEREFLECTCUBE\n", " reflectcube"},
677         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678         {"#define USEBOUNCEGRID\n", " bouncegrid"},
679         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
680 };
681
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
701 };
702
703 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721 };
722
723 struct r_glsl_permutation_s;
724 typedef struct r_glsl_permutation_s
725 {
726         /// hash lookup data
727         struct r_glsl_permutation_s *hashnext;
728         unsigned int mode;
729         unsigned int permutation;
730
731         /// indicates if we have tried compiling this permutation already
732         qboolean compiled;
733         /// 0 if compilation failed
734         int program;
735         // texture units assigned to each detected uniform
736         int tex_Texture_First;
737         int tex_Texture_Second;
738         int tex_Texture_GammaRamps;
739         int tex_Texture_Normal;
740         int tex_Texture_Color;
741         int tex_Texture_Gloss;
742         int tex_Texture_Glow;
743         int tex_Texture_SecondaryNormal;
744         int tex_Texture_SecondaryColor;
745         int tex_Texture_SecondaryGloss;
746         int tex_Texture_SecondaryGlow;
747         int tex_Texture_Pants;
748         int tex_Texture_Shirt;
749         int tex_Texture_FogHeightTexture;
750         int tex_Texture_FogMask;
751         int tex_Texture_Lightmap;
752         int tex_Texture_Deluxemap;
753         int tex_Texture_Attenuation;
754         int tex_Texture_Cube;
755         int tex_Texture_Refraction;
756         int tex_Texture_Reflection;
757         int tex_Texture_ShadowMap2D;
758         int tex_Texture_CubeProjection;
759         int tex_Texture_ScreenDepth;
760         int tex_Texture_ScreenNormalMap;
761         int tex_Texture_ScreenDiffuse;
762         int tex_Texture_ScreenSpecular;
763         int tex_Texture_ReflectMask;
764         int tex_Texture_ReflectCube;
765         int tex_Texture_BounceGrid;
766         /// locations of detected uniforms in program object, or -1 if not found
767         int loc_Texture_First;
768         int loc_Texture_Second;
769         int loc_Texture_GammaRamps;
770         int loc_Texture_Normal;
771         int loc_Texture_Color;
772         int loc_Texture_Gloss;
773         int loc_Texture_Glow;
774         int loc_Texture_SecondaryNormal;
775         int loc_Texture_SecondaryColor;
776         int loc_Texture_SecondaryGloss;
777         int loc_Texture_SecondaryGlow;
778         int loc_Texture_Pants;
779         int loc_Texture_Shirt;
780         int loc_Texture_FogHeightTexture;
781         int loc_Texture_FogMask;
782         int loc_Texture_Lightmap;
783         int loc_Texture_Deluxemap;
784         int loc_Texture_Attenuation;
785         int loc_Texture_Cube;
786         int loc_Texture_Refraction;
787         int loc_Texture_Reflection;
788         int loc_Texture_ShadowMap2D;
789         int loc_Texture_CubeProjection;
790         int loc_Texture_ScreenDepth;
791         int loc_Texture_ScreenNormalMap;
792         int loc_Texture_ScreenDiffuse;
793         int loc_Texture_ScreenSpecular;
794         int loc_Texture_ReflectMask;
795         int loc_Texture_ReflectCube;
796         int loc_Texture_BounceGrid;
797         int loc_Alpha;
798         int loc_BloomBlur_Parameters;
799         int loc_ClientTime;
800         int loc_Color_Ambient;
801         int loc_Color_Diffuse;
802         int loc_Color_Specular;
803         int loc_Color_Glow;
804         int loc_Color_Pants;
805         int loc_Color_Shirt;
806         int loc_DeferredColor_Ambient;
807         int loc_DeferredColor_Diffuse;
808         int loc_DeferredColor_Specular;
809         int loc_DeferredMod_Diffuse;
810         int loc_DeferredMod_Specular;
811         int loc_DistortScaleRefractReflect;
812         int loc_EyePosition;
813         int loc_FogColor;
814         int loc_FogHeightFade;
815         int loc_FogPlane;
816         int loc_FogPlaneViewDist;
817         int loc_FogRangeRecip;
818         int loc_LightColor;
819         int loc_LightDir;
820         int loc_LightPosition;
821         int loc_OffsetMapping_ScaleSteps;
822         int loc_PixelSize;
823         int loc_ReflectColor;
824         int loc_ReflectFactor;
825         int loc_ReflectOffset;
826         int loc_RefractColor;
827         int loc_Saturation;
828         int loc_ScreenCenterRefractReflect;
829         int loc_ScreenScaleRefractReflect;
830         int loc_ScreenToDepth;
831         int loc_ShadowMap_Parameters;
832         int loc_ShadowMap_TextureScale;
833         int loc_SpecularPower;
834         int loc_UserVec1;
835         int loc_UserVec2;
836         int loc_UserVec3;
837         int loc_UserVec4;
838         int loc_ViewTintColor;
839         int loc_ViewToLight;
840         int loc_ModelToLight;
841         int loc_TexMatrix;
842         int loc_BackgroundTexMatrix;
843         int loc_ModelViewProjectionMatrix;
844         int loc_ModelViewMatrix;
845         int loc_PixelToScreenTexCoord;
846         int loc_ModelToReflectCube;
847         int loc_ShadowMapMatrix;
848         int loc_BloomColorSubtract;
849         int loc_NormalmapScrollBlend;
850         int loc_BounceGridMatrix;
851         int loc_BounceGridIntensity;
852 }
853 r_glsl_permutation_t;
854
855 #define SHADERPERMUTATION_HASHSIZE 256
856
857
858 // non-degradable "lightweight" shader parameters to keep the permutations simpler
859 // these can NOT degrade! only use for simple stuff
860 enum
861 {
862         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
863         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
864         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
867         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
868         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 };
870 #define SHADERSTATICPARMS_COUNT 7
871
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
874
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
877 qboolean R_CompileShader_CheckStaticParms(void)
878 {
879         static int r_compileshader_staticparms_save[1];
880         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
881         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
882
883         // detect all
884         if (r_glsl_saturation_redcompensate.integer)
885                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
886         if (r_glsl_vertextextureblend_usebothalphas.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
888         if (r_shadow_glossexact.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
890         if (r_glsl_postprocess.integer)
891         {
892                 if (r_glsl_postprocess_uservec1_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
894                 if (r_glsl_postprocess_uservec2_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
896                 if (r_glsl_postprocess_uservec3_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
898                 if (r_glsl_postprocess_uservec4_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900         }
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921 }
922
923 /// information about each possible shader permutation
924 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
925 /// currently selected permutation
926 r_glsl_permutation_t *r_glsl_permutation;
927 /// storage for permutations linked in the hash table
928 memexpandablearray_t r_glsl_permutationarray;
929
930 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 {
932         //unsigned int hashdepth = 0;
933         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
934         r_glsl_permutation_t *p;
935         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936         {
937                 if (p->mode == mode && p->permutation == permutation)
938                 {
939                         //if (hashdepth > 10)
940                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
941                         return p;
942                 }
943                 //hashdepth++;
944         }
945         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946         p->mode = mode;
947         p->permutation = permutation;
948         p->hashnext = r_glsl_permutationhash[mode][hashindex];
949         r_glsl_permutationhash[mode][hashindex] = p;
950         //if (hashdepth > 10)
951         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
952         return p;
953 }
954
955 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
956 {
957         char *shaderstring;
958         if (!filename || !filename[0])
959                 return NULL;
960         if (!strcmp(filename, "glsl/default.glsl"))
961         {
962                 if (!glslshaderstring)
963                 {
964                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
965                         if (glslshaderstring)
966                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
967                         else
968                                 glslshaderstring = (char *)builtinshaderstring;
969                 }
970                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
971                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
972                 return shaderstring;
973         }
974         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
975         if (shaderstring)
976         {
977                 if (printfromdisknotice)
978                         Con_DPrintf("from disk %s... ", filename);
979                 return shaderstring;
980         }
981         return shaderstring;
982 }
983
984 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
985 {
986         int i;
987         int sampler;
988         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
989         char *vertexstring, *geometrystring, *fragmentstring;
990         char permutationname[256];
991         int vertstrings_count = 0;
992         int geomstrings_count = 0;
993         int fragstrings_count = 0;
994         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
997
998         if (p->compiled)
999                 return;
1000         p->compiled = true;
1001         p->program = 0;
1002
1003         permutationname[0] = 0;
1004         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1005         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1006         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007
1008         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009
1010         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1011         if(vid.support.gl20shaders130)
1012         {
1013                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1014                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1015                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1016                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1017                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1018                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1019         }
1020
1021         // the first pretext is which type of shader to compile as
1022         // (later these will all be bound together as a program object)
1023         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1024         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1025         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026
1027         // the second pretext is the mode (for example a light source)
1028         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1029         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1030         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1031         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032
1033         // now add all the permutation pretexts
1034         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035         {
1036                 if (permutation & (1<<i))
1037                 {
1038                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1041                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1042                 }
1043                 else
1044                 {
1045                         // keep line numbers correct
1046                         vertstrings_list[vertstrings_count++] = "\n";
1047                         geomstrings_list[geomstrings_count++] = "\n";
1048                         fragstrings_list[fragstrings_count++] = "\n";
1049                 }
1050         }
1051
1052         // add static parms
1053         R_CompileShader_AddStaticParms(mode, permutation);
1054         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1055         vertstrings_count += shaderstaticparms_count;
1056         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1057         geomstrings_count += shaderstaticparms_count;
1058         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         fragstrings_count += shaderstaticparms_count;
1060
1061         // now append the shader text itself
1062         vertstrings_list[vertstrings_count++] = vertexstring;
1063         geomstrings_list[geomstrings_count++] = geometrystring;
1064         fragstrings_list[fragstrings_count++] = fragmentstring;
1065
1066         // if any sources were NULL, clear the respective list
1067         if (!vertexstring)
1068                 vertstrings_count = 0;
1069         if (!geometrystring)
1070                 geomstrings_count = 0;
1071         if (!fragmentstring)
1072                 fragstrings_count = 0;
1073
1074         // compile the shader program
1075         if (vertstrings_count + geomstrings_count + fragstrings_count)
1076                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1077         if (p->program)
1078         {
1079                 CHECKGLERROR
1080                 qglUseProgram(p->program);CHECKGLERROR
1081                 // look up all the uniform variable names we care about, so we don't
1082                 // have to look them up every time we set them
1083
1084                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1085                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1086                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1087                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1088                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1089                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1090                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1091                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1092                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1093                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1094                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1095                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1096                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1097                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1098                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1099                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1100                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1101                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1102                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1103                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1104                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1105                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1106                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1107                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1108                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1109                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1110                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1111                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1112                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1113                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1114                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1115                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1116                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1117                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1118                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1119                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1120                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1121                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1122                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1123                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1124                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1125                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1126                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1127                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1128                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1129                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1130                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1131                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1132                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1133                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1134                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1135                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1136                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1137                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1138                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1139                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1140                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1141                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1142                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1143                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1144                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1145                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1146                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1147                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1148                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1149                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1150                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1151                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1152                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1153                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1154                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1155                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1156                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1157                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1158                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1159                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1160                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1161                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1162                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1163                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1164                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1165                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1166                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1167                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1168                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1169                 // initialize the samplers to refer to the texture units we use
1170                 p->tex_Texture_First = -1;
1171                 p->tex_Texture_Second = -1;
1172                 p->tex_Texture_GammaRamps = -1;
1173                 p->tex_Texture_Normal = -1;
1174                 p->tex_Texture_Color = -1;
1175                 p->tex_Texture_Gloss = -1;
1176                 p->tex_Texture_Glow = -1;
1177                 p->tex_Texture_SecondaryNormal = -1;
1178                 p->tex_Texture_SecondaryColor = -1;
1179                 p->tex_Texture_SecondaryGloss = -1;
1180                 p->tex_Texture_SecondaryGlow = -1;
1181                 p->tex_Texture_Pants = -1;
1182                 p->tex_Texture_Shirt = -1;
1183                 p->tex_Texture_FogHeightTexture = -1;
1184                 p->tex_Texture_FogMask = -1;
1185                 p->tex_Texture_Lightmap = -1;
1186                 p->tex_Texture_Deluxemap = -1;
1187                 p->tex_Texture_Attenuation = -1;
1188                 p->tex_Texture_Cube = -1;
1189                 p->tex_Texture_Refraction = -1;
1190                 p->tex_Texture_Reflection = -1;
1191                 p->tex_Texture_ShadowMap2D = -1;
1192                 p->tex_Texture_CubeProjection = -1;
1193                 p->tex_Texture_ScreenDepth = -1;
1194                 p->tex_Texture_ScreenNormalMap = -1;
1195                 p->tex_Texture_ScreenDiffuse = -1;
1196                 p->tex_Texture_ScreenSpecular = -1;
1197                 p->tex_Texture_ReflectMask = -1;
1198                 p->tex_Texture_ReflectCube = -1;
1199                 p->tex_Texture_BounceGrid = -1;
1200                 sampler = 0;
1201                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1202                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1203                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1204                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1205                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1206                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1207                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1211                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1212                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1213                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1214                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1215                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1216                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1217                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1218                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1219                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1220                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1221                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1222                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1223                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1227                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1229                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1230                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1231                 CHECKGLERROR
1232                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1233         }
1234         else
1235                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1236
1237         // free the strings
1238         if (vertexstring)
1239                 Mem_Free(vertexstring);
1240         if (geometrystring)
1241                 Mem_Free(geometrystring);
1242         if (fragmentstring)
1243                 Mem_Free(fragmentstring);
1244 }
1245
1246 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 {
1248         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1249         if (r_glsl_permutation != perm)
1250         {
1251                 r_glsl_permutation = perm;
1252                 if (!r_glsl_permutation->program)
1253                 {
1254                         if (!r_glsl_permutation->compiled)
1255                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1256                         if (!r_glsl_permutation->program)
1257                         {
1258                                 // remove features until we find a valid permutation
1259                                 int i;
1260                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261                                 {
1262                                         // reduce i more quickly whenever it would not remove any bits
1263                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1264                                         if (!(permutation & j))
1265                                                 continue;
1266                                         permutation -= j;
1267                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1268                                         if (!r_glsl_permutation->compiled)
1269                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                                         if (r_glsl_permutation->program)
1271                                                 break;
1272                                 }
1273                                 if (i >= SHADERPERMUTATION_COUNT)
1274                                 {
1275                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1276                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1277                                         qglUseProgram(0);CHECKGLERROR
1278                                         return; // no bit left to clear, entire mode is broken
1279                                 }
1280                         }
1281                 }
1282                 CHECKGLERROR
1283                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284         }
1285         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1286         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1287         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1288 }
1289
1290 #ifdef SUPPORTD3D
1291
1292 #ifdef SUPPORTD3D
1293 #include <d3d9.h>
1294 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1295 extern D3DCAPS9 vid_d3d9caps;
1296 #endif
1297
1298 struct r_hlsl_permutation_s;
1299 typedef struct r_hlsl_permutation_s
1300 {
1301         /// hash lookup data
1302         struct r_hlsl_permutation_s *hashnext;
1303         unsigned int mode;
1304         unsigned int permutation;
1305
1306         /// indicates if we have tried compiling this permutation already
1307         qboolean compiled;
1308         /// NULL if compilation failed
1309         IDirect3DVertexShader9 *vertexshader;
1310         IDirect3DPixelShader9 *pixelshader;
1311 }
1312 r_hlsl_permutation_t;
1313
1314 typedef enum D3DVSREGISTER_e
1315 {
1316         D3DVSREGISTER_TexMatrix = 0, // float4x4
1317         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1318         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1319         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1320         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1321         D3DVSREGISTER_ModelToLight = 20, // float4x4
1322         D3DVSREGISTER_EyePosition = 24,
1323         D3DVSREGISTER_FogPlane = 25,
1324         D3DVSREGISTER_LightDir = 26,
1325         D3DVSREGISTER_LightPosition = 27,
1326 }
1327 D3DVSREGISTER_t;
1328
1329 typedef enum D3DPSREGISTER_e
1330 {
1331         D3DPSREGISTER_Alpha = 0,
1332         D3DPSREGISTER_BloomBlur_Parameters = 1,
1333         D3DPSREGISTER_ClientTime = 2,
1334         D3DPSREGISTER_Color_Ambient = 3,
1335         D3DPSREGISTER_Color_Diffuse = 4,
1336         D3DPSREGISTER_Color_Specular = 5,
1337         D3DPSREGISTER_Color_Glow = 6,
1338         D3DPSREGISTER_Color_Pants = 7,
1339         D3DPSREGISTER_Color_Shirt = 8,
1340         D3DPSREGISTER_DeferredColor_Ambient = 9,
1341         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1342         D3DPSREGISTER_DeferredColor_Specular = 11,
1343         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1344         D3DPSREGISTER_DeferredMod_Specular = 13,
1345         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1346         D3DPSREGISTER_EyePosition = 15, // unused
1347         D3DPSREGISTER_FogColor = 16,
1348         D3DPSREGISTER_FogHeightFade = 17,
1349         D3DPSREGISTER_FogPlane = 18,
1350         D3DPSREGISTER_FogPlaneViewDist = 19,
1351         D3DPSREGISTER_FogRangeRecip = 20,
1352         D3DPSREGISTER_LightColor = 21,
1353         D3DPSREGISTER_LightDir = 22, // unused
1354         D3DPSREGISTER_LightPosition = 23,
1355         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1356         D3DPSREGISTER_PixelSize = 25,
1357         D3DPSREGISTER_ReflectColor = 26,
1358         D3DPSREGISTER_ReflectFactor = 27,
1359         D3DPSREGISTER_ReflectOffset = 28,
1360         D3DPSREGISTER_RefractColor = 29,
1361         D3DPSREGISTER_Saturation = 30,
1362         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1363         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1364         D3DPSREGISTER_ScreenToDepth = 33,
1365         D3DPSREGISTER_ShadowMap_Parameters = 34,
1366         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1367         D3DPSREGISTER_SpecularPower = 36,
1368         D3DPSREGISTER_UserVec1 = 37,
1369         D3DPSREGISTER_UserVec2 = 38,
1370         D3DPSREGISTER_UserVec3 = 39,
1371         D3DPSREGISTER_UserVec4 = 40,
1372         D3DPSREGISTER_ViewTintColor = 41,
1373         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1374         D3DPSREGISTER_BloomColorSubtract = 43,
1375         D3DPSREGISTER_ViewToLight = 44, // float4x4
1376         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1377         D3DPSREGISTER_NormalmapScrollBlend = 52,
1378         // next at 53
1379 }
1380 D3DPSREGISTER_t;
1381
1382 /// information about each possible shader permutation
1383 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1384 /// currently selected permutation
1385 r_hlsl_permutation_t *r_hlsl_permutation;
1386 /// storage for permutations linked in the hash table
1387 memexpandablearray_t r_hlsl_permutationarray;
1388
1389 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 {
1391         //unsigned int hashdepth = 0;
1392         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1393         r_hlsl_permutation_t *p;
1394         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395         {
1396                 if (p->mode == mode && p->permutation == permutation)
1397                 {
1398                         //if (hashdepth > 10)
1399                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1400                         return p;
1401                 }
1402                 //hashdepth++;
1403         }
1404         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405         p->mode = mode;
1406         p->permutation = permutation;
1407         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1408         r_hlsl_permutationhash[mode][hashindex] = p;
1409         //if (hashdepth > 10)
1410         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1411         return p;
1412 }
1413
1414 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1415 {
1416         char *shaderstring;
1417         if (!filename || !filename[0])
1418                 return NULL;
1419         if (!strcmp(filename, "hlsl/default.hlsl"))
1420         {
1421                 if (!hlslshaderstring)
1422                 {
1423                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424                         if (hlslshaderstring)
1425                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426                         else
1427                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1428                 }
1429                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1430                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1431                 return shaderstring;
1432         }
1433         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1434         if (shaderstring)
1435         {
1436                 if (printfromdisknotice)
1437                         Con_DPrintf("from disk %s... ", filename);
1438                 return shaderstring;
1439         }
1440         return shaderstring;
1441 }
1442
1443 #include <d3dx9.h>
1444 //#include <d3dx9shader.h>
1445 //#include <d3dx9mesh.h>
1446
1447 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 {
1449         DWORD *vsbin = NULL;
1450         DWORD *psbin = NULL;
1451         fs_offset_t vsbinsize;
1452         fs_offset_t psbinsize;
1453 //      IDirect3DVertexShader9 *vs = NULL;
1454 //      IDirect3DPixelShader9 *ps = NULL;
1455         ID3DXBuffer *vslog = NULL;
1456         ID3DXBuffer *vsbuffer = NULL;
1457         ID3DXConstantTable *vsconstanttable = NULL;
1458         ID3DXBuffer *pslog = NULL;
1459         ID3DXBuffer *psbuffer = NULL;
1460         ID3DXConstantTable *psconstanttable = NULL;
1461         int vsresult = 0;
1462         int psresult = 0;
1463         char temp[MAX_INPUTLINE];
1464         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1465         qboolean debugshader = gl_paranoid.integer != 0;
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1468         if (!debugshader)
1469         {
1470                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1471                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472         }
1473         if ((!vsbin && vertstring) || (!psbin && fragstring))
1474         {
1475                 const char* dllnames_d3dx9 [] =
1476                 {
1477                         "d3dx9_43.dll",
1478                         "d3dx9_42.dll",
1479                         "d3dx9_41.dll",
1480                         "d3dx9_40.dll",
1481                         "d3dx9_39.dll",
1482                         "d3dx9_38.dll",
1483                         "d3dx9_37.dll",
1484                         "d3dx9_36.dll",
1485                         "d3dx9_35.dll",
1486                         "d3dx9_34.dll",
1487                         "d3dx9_33.dll",
1488                         "d3dx9_32.dll",
1489                         "d3dx9_31.dll",
1490                         "d3dx9_30.dll",
1491                         "d3dx9_29.dll",
1492                         "d3dx9_28.dll",
1493                         "d3dx9_27.dll",
1494                         "d3dx9_26.dll",
1495                         "d3dx9_25.dll",
1496                         "d3dx9_24.dll",
1497                         NULL
1498                 };
1499                 dllhandle_t d3dx9_dll = NULL;
1500                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1501                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1502                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1503                 dllfunction_t d3dx9_dllfuncs[] =
1504                 {
1505                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1506                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1507                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1508                         {NULL, NULL}
1509                 };
1510                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511                 {
1512                         DWORD shaderflags = 0;
1513                         if (debugshader)
1514                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1515                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1516                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1517                         if (vertstring && vertstring[0])
1518                         {
1519                                 if (debugshader)
1520                                 {
1521 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1522 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1523                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1524                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1525                                 }
1526                                 else
1527                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1528                                 if (vsbuffer)
1529                                 {
1530                                         vsbinsize = vsbuffer->GetBufferSize();
1531                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1532                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1533                                         vsbuffer->Release();
1534                                 }
1535                                 if (vslog)
1536                                 {
1537                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1538                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1539                                         vslog->Release();
1540                                 }
1541                         }
1542                         if (fragstring && fragstring[0])
1543                         {
1544                                 if (debugshader)
1545                                 {
1546 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1547 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1548                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1549                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1550                                 }
1551                                 else
1552                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1553                                 if (psbuffer)
1554                                 {
1555                                         psbinsize = psbuffer->GetBufferSize();
1556                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1557                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1558                                         psbuffer->Release();
1559                                 }
1560                                 if (pslog)
1561                                 {
1562                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1563                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1564                                         pslog->Release();
1565                                 }
1566                         }
1567                         Sys_UnloadLibrary(&d3dx9_dll);
1568                 }
1569                 else
1570                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1571         }
1572         if (vsbin && psbin)
1573         {
1574                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1575                 if (FAILED(vsresult))
1576                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1577                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1578                 if (FAILED(psresult))
1579                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580         }
1581         // free the shader data
1582         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1583         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1584 }
1585
1586 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1587 {
1588         int i;
1589         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1590         int vertstring_length = 0;
1591         int geomstring_length = 0;
1592         int fragstring_length = 0;
1593         char *t;
1594         char *vertexstring, *geometrystring, *fragmentstring;
1595         char *vertstring, *geomstring, *fragstring;
1596         char permutationname[256];
1597         char cachename[256];
1598         int vertstrings_count = 0;
1599         int geomstrings_count = 0;
1600         int fragstrings_count = 0;
1601         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1604
1605         if (p->compiled)
1606                 return;
1607         p->compiled = true;
1608         p->vertexshader = NULL;
1609         p->pixelshader = NULL;
1610
1611         permutationname[0] = 0;
1612         cachename[0] = 0;
1613         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1614         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1615         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616
1617         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1618         strlcat(cachename, "hlsl/", sizeof(cachename));
1619
1620         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1621         vertstrings_count = 0;
1622         geomstrings_count = 0;
1623         fragstrings_count = 0;
1624         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1625         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1626         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627
1628         // the first pretext is which type of shader to compile as
1629         // (later these will all be bound together as a program object)
1630         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1631         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1632         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633
1634         // the second pretext is the mode (for example a light source)
1635         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1636         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1637         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1638         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1639         strlcat(cachename, modeinfo->name, sizeof(cachename));
1640
1641         // now add all the permutation pretexts
1642         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643         {
1644                 if (permutation & (1<<i))
1645                 {
1646                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1649                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1650                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1651                 }
1652                 else
1653                 {
1654                         // keep line numbers correct
1655                         vertstrings_list[vertstrings_count++] = "\n";
1656                         geomstrings_list[geomstrings_count++] = "\n";
1657                         fragstrings_list[fragstrings_count++] = "\n";
1658                 }
1659         }
1660
1661         // add static parms
1662         R_CompileShader_AddStaticParms(mode, permutation);
1663         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1664         vertstrings_count += shaderstaticparms_count;
1665         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1666         geomstrings_count += shaderstaticparms_count;
1667         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         fragstrings_count += shaderstaticparms_count;
1669
1670         // replace spaces in the cachename with _ characters
1671         for (i = 0;cachename[i];i++)
1672                 if (cachename[i] == ' ')
1673                         cachename[i] = '_';
1674
1675         // now append the shader text itself
1676         vertstrings_list[vertstrings_count++] = vertexstring;
1677         geomstrings_list[geomstrings_count++] = geometrystring;
1678         fragstrings_list[fragstrings_count++] = fragmentstring;
1679
1680         // if any sources were NULL, clear the respective list
1681         if (!vertexstring)
1682                 vertstrings_count = 0;
1683         if (!geometrystring)
1684                 geomstrings_count = 0;
1685         if (!fragmentstring)
1686                 fragstrings_count = 0;
1687
1688         vertstring_length = 0;
1689         for (i = 0;i < vertstrings_count;i++)
1690                 vertstring_length += strlen(vertstrings_list[i]);
1691         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1692         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1693                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694
1695         geomstring_length = 0;
1696         for (i = 0;i < geomstrings_count;i++)
1697                 geomstring_length += strlen(geomstrings_list[i]);
1698         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1699         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1700                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701
1702         fragstring_length = 0;
1703         for (i = 0;i < fragstrings_count;i++)
1704                 fragstring_length += strlen(fragstrings_list[i]);
1705         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1706         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1707                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708
1709         // try to load the cached shader, or generate one
1710         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711
1712         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1713                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714         else
1715                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1716
1717         // free the strings
1718         if (vertstring)
1719                 Mem_Free(vertstring);
1720         if (geomstring)
1721                 Mem_Free(geomstring);
1722         if (fragstring)
1723                 Mem_Free(fragstring);
1724         if (vertexstring)
1725                 Mem_Free(vertexstring);
1726         if (geometrystring)
1727                 Mem_Free(geometrystring);
1728         if (fragmentstring)
1729                 Mem_Free(fragmentstring);
1730 }
1731
1732 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1733 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1734 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);}
1735 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);}
1736 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);}
1737 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);}
1738
1739 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1745
1746 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 {
1748         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1749         if (r_hlsl_permutation != perm)
1750         {
1751                 r_hlsl_permutation = perm;
1752                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753                 {
1754                         if (!r_hlsl_permutation->compiled)
1755                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1756                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757                         {
1758                                 // remove features until we find a valid permutation
1759                                 int i;
1760                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761                                 {
1762                                         // reduce i more quickly whenever it would not remove any bits
1763                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1764                                         if (!(permutation & j))
1765                                                 continue;
1766                                         permutation -= j;
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         if (!r_hlsl_permutation->compiled)
1769                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1770                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1771                                                 break;
1772                                 }
1773                                 if (i >= SHADERPERMUTATION_COUNT)
1774                                 {
1775                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1776                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1777                                         return; // no bit left to clear, entire mode is broken
1778                                 }
1779                         }
1780                 }
1781                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1782                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783         }
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1785         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1786         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1787 }
1788 #endif
1789
1790 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 {
1792         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1794         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1795         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1796 }
1797
1798 void R_GLSL_Restart_f(void)
1799 {
1800         unsigned int i, limit;
1801         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1802                 Mem_Free(glslshaderstring);
1803         glslshaderstring = NULL;
1804         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1805                 Mem_Free(hlslshaderstring);
1806         hlslshaderstring = NULL;
1807         switch(vid.renderpath)
1808         {
1809         case RENDERPATH_D3D9:
1810 #ifdef SUPPORTD3D
1811                 {
1812                         r_hlsl_permutation_t *p;
1813                         r_hlsl_permutation = NULL;
1814                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1815                         for (i = 0;i < limit;i++)
1816                         {
1817                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818                                 {
1819                                         if (p->vertexshader)
1820                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1821                                         if (p->pixelshader)
1822                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1823                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1824                                 }
1825                         }
1826                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1827                 }
1828 #endif
1829                 break;
1830         case RENDERPATH_D3D10:
1831                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832                 break;
1833         case RENDERPATH_D3D11:
1834                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835                 break;
1836         case RENDERPATH_GL20:
1837         case RENDERPATH_GLES2:
1838                 {
1839                         r_glsl_permutation_t *p;
1840                         r_glsl_permutation = NULL;
1841                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1842                         for (i = 0;i < limit;i++)
1843                         {
1844                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845                                 {
1846                                         GL_Backend_FreeProgram(p->program);
1847                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1848                                 }
1849                         }
1850                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1851                 }
1852                 break;
1853         case RENDERPATH_GL11:
1854         case RENDERPATH_GL13:
1855         case RENDERPATH_GLES1:
1856                 break;
1857         case RENDERPATH_SOFT:
1858                 break;
1859         }
1860 }
1861
1862 void R_GLSL_DumpShader_f(void)
1863 {
1864         int i;
1865         qfile_t *file;
1866
1867         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1868         if (file)
1869         {
1870                 FS_Print(file, "/* The engine may define the following macros:\n");
1871                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1872                 for (i = 0;i < SHADERMODE_COUNT;i++)
1873                         FS_Print(file, glslshadermodeinfo[i].pretext);
1874                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1875                         FS_Print(file, shaderpermutationinfo[i].pretext);
1876                 FS_Print(file, "*/\n");
1877                 FS_Print(file, builtinshaderstring);
1878                 FS_Close(file);
1879                 Con_Printf("glsl/default.glsl written\n");
1880         }
1881         else
1882                 Con_Printf("failed to write to glsl/default.glsl\n");
1883
1884         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinhlslshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("hlsl/default.hlsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1900 }
1901
1902 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1903 {
1904         if (!second)
1905                 texturemode = GL_MODULATE;
1906         switch (vid.renderpath)
1907         {
1908         case RENDERPATH_D3D9:
1909 #ifdef SUPPORTD3D
1910                 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))));
1911                 R_Mesh_TexBind(GL20TU_FIRST , first );
1912                 R_Mesh_TexBind(GL20TU_SECOND, second);
1913 #endif
1914                 break;
1915         case RENDERPATH_D3D10:
1916                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1917                 break;
1918         case RENDERPATH_D3D11:
1919                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920                 break;
1921         case RENDERPATH_GL20:
1922         case RENDERPATH_GLES2:
1923                 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))));
1924                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1925                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1926                 break;
1927         case RENDERPATH_GL13:
1928         case RENDERPATH_GLES1:
1929                 R_Mesh_TexBind(0, first );
1930                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1931                 R_Mesh_TexBind(1, second);
1932                 if (second)
1933                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1934                 break;
1935         case RENDERPATH_GL11:
1936                 R_Mesh_TexBind(0, first );
1937                 break;
1938         case RENDERPATH_SOFT:
1939                 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))));
1940                 R_Mesh_TexBind(GL20TU_FIRST , first );
1941                 R_Mesh_TexBind(GL20TU_SECOND, second);
1942                 break;
1943         }
1944 }
1945
1946 void R_SetupShader_DepthOrShadow(void)
1947 {
1948         switch (vid.renderpath)
1949         {
1950         case RENDERPATH_D3D9:
1951 #ifdef SUPPORTD3D
1952                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1964                 break;
1965         case RENDERPATH_GL13:
1966         case RENDERPATH_GLES1:
1967                 R_Mesh_TexBind(0, 0);
1968                 R_Mesh_TexBind(1, 0);
1969                 break;
1970         case RENDERPATH_GL11:
1971                 R_Mesh_TexBind(0, 0);
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1975                 break;
1976         }
1977 }
1978
1979 void R_SetupShader_ShowDepth(void)
1980 {
1981         switch (vid.renderpath)
1982         {
1983         case RENDERPATH_D3D9:
1984 #ifdef SUPPORTHLSL
1985                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1986 #endif
1987                 break;
1988         case RENDERPATH_D3D10:
1989                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1990                 break;
1991         case RENDERPATH_D3D11:
1992                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1993                 break;
1994         case RENDERPATH_GL20:
1995         case RENDERPATH_GLES2:
1996                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1997                 break;
1998         case RENDERPATH_GL13:
1999         case RENDERPATH_GLES1:
2000                 break;
2001         case RENDERPATH_GL11:
2002                 break;
2003         case RENDERPATH_SOFT:
2004                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2005                 break;
2006         }
2007 }
2008
2009 extern qboolean r_shadow_usingdeferredprepass;
2010 extern cvar_t r_shadow_deferred_8bitrange;
2011 extern rtexture_t *r_shadow_attenuationgradienttexture;
2012 extern rtexture_t *r_shadow_attenuation2dtexture;
2013 extern rtexture_t *r_shadow_attenuation3dtexture;
2014 extern qboolean r_shadow_usingshadowmap2d;
2015 extern qboolean r_shadow_usingshadowmaportho;
2016 extern float r_shadow_shadowmap_texturescale[2];
2017 extern float r_shadow_shadowmap_parameters[4];
2018 extern qboolean r_shadow_shadowmapvsdct;
2019 extern qboolean r_shadow_shadowmapsampler;
2020 extern int r_shadow_shadowmappcf;
2021 extern rtexture_t *r_shadow_shadowmap2dtexture;
2022 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2023 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2024 extern matrix4x4_t r_shadow_shadowmapmatrix;
2025 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2026 extern int r_shadow_prepass_width;
2027 extern int r_shadow_prepass_height;
2028 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2029 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2030 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2031 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2032 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2033
2034 #define BLENDFUNC_ALLOWS_COLORMOD      1
2035 #define BLENDFUNC_ALLOWS_FOG           2
2036 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2037 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2038 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2039 static int R_BlendFuncFlags(int src, int dst)
2040 {
2041         int r = 0;
2042
2043         // a blendfunc allows colormod if:
2044         // a) it can never keep the destination pixel invariant, or
2045         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2046         // this is to prevent unintended side effects from colormod
2047
2048         // a blendfunc allows fog if:
2049         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2050         // this is to prevent unintended side effects from fog
2051
2052         // these checks are the output of fogeval.pl
2053
2054         r |= BLENDFUNC_ALLOWS_COLORMOD;
2055         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2056         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2057         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2058         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2059         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2062         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2064         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2065         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2066         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2067         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2068         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2069         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2070         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2072         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2073         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2074         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2075         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2076
2077         return r;
2078 }
2079
2080 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)
2081 {
2082         // select a permutation of the lighting shader appropriate to this
2083         // combination of texture, entity, light source, and fogging, only use the
2084         // minimum features necessary to avoid wasting rendering time in the
2085         // fragment shader on features that are not being used
2086         unsigned int permutation = 0;
2087         unsigned int mode = 0;
2088         int blendfuncflags;
2089         static float dummy_colormod[3] = {1, 1, 1};
2090         float *colormod = rsurface.colormod;
2091         float m16f[16];
2092         matrix4x4_t tempmatrix;
2093         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2094         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2095                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2096         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2097                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2098         if (rsurfacepass == RSURFPASS_BACKGROUND)
2099         {
2100                 // distorted background
2101                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2102                 {
2103                         mode = SHADERMODE_WATER;
2104                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2105                         {
2106                                 // this is the right thing to do for wateralpha
2107                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2108                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2109                         }
2110                         else
2111                         {
2112                                 // this is the right thing to do for entity alpha
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                 }
2117                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2118                 {
2119                         mode = SHADERMODE_REFRACTION;
2120                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2122                 }
2123                 else
2124                 {
2125                         mode = SHADERMODE_GENERIC;
2126                         permutation |= SHADERPERMUTATION_DIFFUSE;
2127                         GL_BlendFunc(GL_ONE, GL_ZERO);
2128                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2129                 }
2130         }
2131         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2132         {
2133                 if (r_glsl_offsetmapping.integer)
2134                 {
2135                         switch(rsurface.texture->offsetmapping)
2136                         {
2137                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2138                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2140                         case OFFSETMAPPING_OFF: break;
2141                         }
2142                 }
2143                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145                 // normalmap (deferred prepass), may use alpha test on diffuse
2146                 mode = SHADERMODE_DEFERREDGEOMETRY;
2147                 GL_BlendFunc(GL_ONE, GL_ZERO);
2148                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149         }
2150         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151         {
2152                 if (r_glsl_offsetmapping.integer)
2153                 {
2154                         switch(rsurface.texture->offsetmapping)
2155                         {
2156                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2157                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2159                         case OFFSETMAPPING_OFF: break;
2160                         }
2161                 }
2162                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2163                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2164                 // light source
2165                 mode = SHADERMODE_LIGHTSOURCE;
2166                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2167                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2168                 if (diffusescale > 0)
2169                         permutation |= SHADERPERMUTATION_DIFFUSE;
2170                 if (specularscale > 0)
2171                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2172                 if (r_refdef.fogenabled)
2173                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2174                 if (rsurface.texture->colormapping)
2175                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2176                 if (r_shadow_usingshadowmap2d)
2177                 {
2178                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2179                         if(r_shadow_shadowmapvsdct)
2180                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181
2182                         if (r_shadow_shadowmapsampler)
2183                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2184                         if (r_shadow_shadowmappcf > 1)
2185                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2186                         else if (r_shadow_shadowmappcf)
2187                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188                 }
2189                 if (rsurface.texture->reflectmasktexture)
2190                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2191                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2192                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193         }
2194         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195         {
2196                 if (r_glsl_offsetmapping.integer)
2197                 {
2198                         switch(rsurface.texture->offsetmapping)
2199                         {
2200                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203                         case OFFSETMAPPING_OFF: break;
2204                         }
2205                 }
2206                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2208                 // unshaded geometry (fullbright or ambient model lighting)
2209                 mode = SHADERMODE_FLATCOLOR;
2210                 ambientscale = diffusescale = specularscale = 0;
2211                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2212                         permutation |= SHADERPERMUTATION_GLOW;
2213                 if (r_refdef.fogenabled)
2214                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2215                 if (rsurface.texture->colormapping)
2216                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2217                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2218                 {
2219                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2220                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221
2222                         if (r_shadow_shadowmapsampler)
2223                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2224                         if (r_shadow_shadowmappcf > 1)
2225                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2226                         else if (r_shadow_shadowmappcf)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2228                 }
2229                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2230                         permutation |= SHADERPERMUTATION_REFLECTION;
2231                 if (rsurface.texture->reflectmasktexture)
2232                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2234                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235         }
2236         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2237         {
2238                 if (r_glsl_offsetmapping.integer)
2239                 {
2240                         switch(rsurface.texture->offsetmapping)
2241                         {
2242                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2243                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2245                         case OFFSETMAPPING_OFF: break;
2246                         }
2247                 }
2248                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2249                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2250                 // directional model lighting
2251                 mode = SHADERMODE_LIGHTDIRECTION;
2252                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2253                         permutation |= SHADERPERMUTATION_GLOW;
2254                 permutation |= SHADERPERMUTATION_DIFFUSE;
2255                 if (specularscale > 0)
2256                         permutation |= SHADERPERMUTATION_SPECULAR;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265
2266                         if (r_shadow_shadowmapsampler)
2267                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268                         if (r_shadow_shadowmappcf > 1)
2269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270                         else if (r_shadow_shadowmappcf)
2271                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274                         permutation |= SHADERPERMUTATION_REFLECTION;
2275                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2276                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2277                 if (rsurface.texture->reflectmasktexture)
2278                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279                 if (r_shadow_bouncegridtexture)
2280                 {
2281                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2282                         if (r_shadow_bouncegriddirectional)
2283                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2284                 }
2285                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287         }
2288         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2289         {
2290                 if (r_glsl_offsetmapping.integer)
2291                 {
2292                         switch(rsurface.texture->offsetmapping)
2293                         {
2294                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2295                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_OFF: break;
2298                         }
2299                 }
2300                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2301                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2302                 // ambient model lighting
2303                 mode = SHADERMODE_LIGHTDIRECTION;
2304                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2305                         permutation |= SHADERPERMUTATION_GLOW;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmapsampler)
2316                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317                         if (r_shadow_shadowmappcf > 1)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319                         else if (r_shadow_shadowmappcf)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336         }
2337         else
2338         {
2339                 if (r_glsl_offsetmapping.integer)
2340                 {
2341                         switch(rsurface.texture->offsetmapping)
2342                         {
2343                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2344                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2346                         case OFFSETMAPPING_OFF: break;
2347                         }
2348                 }
2349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2350                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2351                 // lightmapped wall
2352                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2353                         permutation |= SHADERPERMUTATION_GLOW;
2354                 if (r_refdef.fogenabled)
2355                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2356                 if (rsurface.texture->colormapping)
2357                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2358                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359                 {
2360                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2361                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362
2363                         if (r_shadow_shadowmapsampler)
2364                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2365                         if (r_shadow_shadowmappcf > 1)
2366                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2367                         else if (r_shadow_shadowmappcf)
2368                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2369                 }
2370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2371                         permutation |= SHADERPERMUTATION_REFLECTION;
2372                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2373                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2374                 if (rsurface.texture->reflectmasktexture)
2375                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2376                 if (FAKELIGHT_ENABLED)
2377                 {
2378                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2379                         mode = SHADERMODE_FAKELIGHT;
2380                         permutation |= SHADERPERMUTATION_DIFFUSE;
2381                         if (specularscale > 0)
2382                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383                 }
2384                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2385                 {
2386                         // deluxemapping (light direction texture)
2387                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2388                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2389                         else
2390                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2391                         permutation |= SHADERPERMUTATION_DIFFUSE;
2392                         if (specularscale > 0)
2393                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394                 }
2395                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2396                 {
2397                         // fake deluxemapping (uniform light direction in tangentspace)
2398                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2399                         permutation |= SHADERPERMUTATION_DIFFUSE;
2400                         if (specularscale > 0)
2401                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402                 }
2403                 else if (rsurface.uselightmaptexture)
2404                 {
2405                         // ordinary lightmapping (q1bsp, q3bsp)
2406                         mode = SHADERMODE_LIGHTMAP;
2407                 }
2408                 else
2409                 {
2410                         // ordinary vertex coloring (q3bsp)
2411                         mode = SHADERMODE_VERTEXCOLOR;
2412                 }
2413                 if (r_shadow_bouncegridtexture)
2414                 {
2415                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416                         if (r_shadow_bouncegriddirectional)
2417                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418                 }
2419                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421         }
2422         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2423                 colormod = dummy_colormod;
2424         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2425                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2426         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2427                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2428         switch(vid.renderpath)
2429         {
2430         case RENDERPATH_D3D9:
2431 #ifdef SUPPORTD3D
2432                 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);
2433                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2434                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2435                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2436                 if (mode == SHADERMODE_LIGHTSOURCE)
2437                 {
2438                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2439                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2440                 }
2441                 else
2442                 {
2443                         if (mode == SHADERMODE_LIGHTDIRECTION)
2444                         {
2445                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2446                         }
2447                 }
2448                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2449                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2450                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2451                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2452                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2453
2454                 if (mode == SHADERMODE_LIGHTSOURCE)
2455                 {
2456                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2457                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2458                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2459                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2460                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2461
2462                         // additive passes are only darkened by fog, not tinted
2463                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2464                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2465                 }
2466                 else
2467                 {
2468                         if (mode == SHADERMODE_FLATCOLOR)
2469                         {
2470                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2471                         }
2472                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2473                         {
2474                                 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]);
2475                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2476                                 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);
2477                                 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);
2478                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2479                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2480                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2481                         }
2482                         else
2483                         {
2484                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2485                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2486                                 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);
2487                                 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);
2488                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2489                         }
2490                         // additive passes are only darkened by fog, not tinted
2491                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2492                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2493                         else
2494                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2495                         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);
2496                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2497                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2498                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2500                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2501                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2502                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2503                         if (mode == SHADERMODE_WATER)
2504                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2505                 }
2506                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2507                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2508                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2509                 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));
2510                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2511                 if (rsurface.texture->pantstexture)
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2513                 else
2514                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2515                 if (rsurface.texture->shirttexture)
2516                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2517                 else
2518                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2519                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2520                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2521                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2522                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2523                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2524                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2525                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2527                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2528                         );
2529                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2530                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2531
2532                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2533                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2534                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2535                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2536                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2537                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2538                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2539                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2540                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2541                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2542                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2543                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2544                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2545                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2546                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2547                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2548                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2549                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2550                 {
2551                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2552                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2553                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2554                 }
2555                 else
2556                 {
2557                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2558                 }
2559 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2560 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2561                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2562                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2563                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2564                 {
2565                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2566                         if (rsurface.rtlight)
2567                         {
2568                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2569                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2570                         }
2571                 }
2572 #endif
2573                 break;
2574         case RENDERPATH_D3D10:
2575                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576                 break;
2577         case RENDERPATH_D3D11:
2578                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2579                 break;
2580         case RENDERPATH_GL20:
2581         case RENDERPATH_GLES2:
2582                 if (!vid.useinterleavedarrays)
2583                 {
2584                         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);
2585                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2586                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2587                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2588                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2589                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2590                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2591                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2592                 }
2593                 else
2594                 {
2595                         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);
2596                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2597                 }
2598                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2599                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2600                 if (mode == SHADERMODE_LIGHTSOURCE)
2601                 {
2602                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2603                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2604                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2605                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2606                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2607                         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);
2608         
2609                         // additive passes are only darkened by fog, not tinted
2610                         if (r_glsl_permutation->loc_FogColor >= 0)
2611                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2612                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2613                 }
2614                 else
2615                 {
2616                         if (mode == SHADERMODE_FLATCOLOR)
2617                         {
2618                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2619                         }
2620                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2621                         {
2622                                 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]);
2623                                 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]);
2624                                 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);
2625                                 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);
2626                                 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);
2627                                 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]);
2628                                 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]);
2629                         }
2630                         else
2631                         {
2632                                 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]);
2633                                 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]);
2634                                 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);
2635                                 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);
2636                                 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);
2637                         }
2638                         // additive passes are only darkened by fog, not tinted
2639                         if (r_glsl_permutation->loc_FogColor >= 0)
2640                         {
2641                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2642                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2643                                 else
2644                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2645                         }
2646                         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);
2647                         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]);
2648                         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]);
2649                         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]);
2650                         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]);
2651                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2652                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2653                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2654                         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]);
2655                 }
2656                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2657                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2658                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2659                 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]);
2660                 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]);
2661
2662                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2663                 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));
2664                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2665                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2666                 {
2667                         if (rsurface.texture->pantstexture)
2668                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2669                         else
2670                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2671                 }
2672                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2673                 {
2674                         if (rsurface.texture->shirttexture)
2675                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2676                         else
2677                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2678                 }
2679                 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]);
2680                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2681                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2682                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2683                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2684                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2685                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2687                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688                         );
2689                 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]);
2690                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2691                 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);}
2692                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2693
2694                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2695                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2696                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2697                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2698                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2699                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2700                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2701                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2702                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2703                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2704                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2705                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2706                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2707                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2708                 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);
2709                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2710                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2711                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2712                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2713                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2714                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2715                 {
2716                         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);
2717                         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);
2718                         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);
2719                 }
2720                 else
2721                 {
2722                         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);
2723                 }
2724                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2725                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2726                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2727                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2728                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2729                 {
2730                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2731                         if (rsurface.rtlight)
2732                         {
2733                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2734                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2735                         }
2736                 }
2737                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2738                 CHECKGLERROR
2739                 break;
2740         case RENDERPATH_GL11:
2741         case RENDERPATH_GL13:
2742         case RENDERPATH_GLES1:
2743                 break;
2744         case RENDERPATH_SOFT:
2745                 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);
2746                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2747                 R_SetupShader_SetPermutationSoft(mode, permutation);
2748                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2749                 if (mode == SHADERMODE_LIGHTSOURCE)
2750                 {
2751                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2752                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2753                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2754                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2755                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2756                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2757         
2758                         // additive passes are only darkened by fog, not tinted
2759                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2760                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2761                 }
2762                 else
2763                 {
2764                         if (mode == SHADERMODE_FLATCOLOR)
2765                         {
2766                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2767                         }
2768                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2769                         {
2770                                 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]);
2771                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2772                                 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);
2773                                 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);
2774                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2775                                 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]);
2776                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2777                         }
2778                         else
2779                         {
2780                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2781                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2782                                 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);
2783                                 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);
2784                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2785                         }
2786                         // additive passes are only darkened by fog, not tinted
2787                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2788                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2789                         else
2790                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2791                         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);
2792                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2793                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2794                         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]);
2795                         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]);
2796                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2797                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2798                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2799                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2800                 }
2801                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2802                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2803                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2804                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2805                 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]);
2806
2807                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2808                 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));
2809                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2810                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2811                 {
2812                         if (rsurface.texture->pantstexture)
2813                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2814                         else
2815                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2816                 }
2817                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2818                 {
2819                         if (rsurface.texture->shirttexture)
2820                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2821                         else
2822                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2823                 }
2824                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2825                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2826                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2827                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2828                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2829                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2830                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2831                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2832                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2833                         );
2834                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2835                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2836
2837                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2838                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2839                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2840                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2841                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2842                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2843                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2844                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2845                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2846                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2847                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2848                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2849                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2850                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2851                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2852                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2853                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2854                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2855                 {
2856                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2857                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2858                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2859                 }
2860                 else
2861                 {
2862                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2863                 }
2864 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2865 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2866                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2867                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2868                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2869                 {
2870                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2871                         if (rsurface.rtlight)
2872                         {
2873                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2874                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2875                         }
2876                 }
2877                 break;
2878         }
2879 }
2880
2881 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2882 {
2883         // select a permutation of the lighting shader appropriate to this
2884         // combination of texture, entity, light source, and fogging, only use the
2885         // minimum features necessary to avoid wasting rendering time in the
2886         // fragment shader on features that are not being used
2887         unsigned int permutation = 0;
2888         unsigned int mode = 0;
2889         const float *lightcolorbase = rtlight->currentcolor;
2890         float ambientscale = rtlight->ambientscale;
2891         float diffusescale = rtlight->diffusescale;
2892         float specularscale = rtlight->specularscale;
2893         // this is the location of the light in view space
2894         vec3_t viewlightorigin;
2895         // this transforms from view space (camera) to light space (cubemap)
2896         matrix4x4_t viewtolight;
2897         matrix4x4_t lighttoview;
2898         float viewtolight16f[16];
2899         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2900         // light source
2901         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2902         if (rtlight->currentcubemap != r_texture_whitecube)
2903                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2904         if (diffusescale > 0)
2905                 permutation |= SHADERPERMUTATION_DIFFUSE;
2906         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2907                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2908         if (r_shadow_usingshadowmap2d)
2909         {
2910                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2911                 if (r_shadow_shadowmapvsdct)
2912                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2913
2914                 if (r_shadow_shadowmapsampler)
2915                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2916                 if (r_shadow_shadowmappcf > 1)
2917                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2918                 else if (r_shadow_shadowmappcf)
2919                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2920         }
2921         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2922         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2923         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2924         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2925         switch(vid.renderpath)
2926         {
2927         case RENDERPATH_D3D9:
2928 #ifdef SUPPORTD3D
2929                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2930                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2931                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2932                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2933                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2934                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2935                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2936                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2937                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2938                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2940
2941                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2942                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
2943                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2944                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2945                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
2946                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2947 #endif
2948                 break;
2949         case RENDERPATH_D3D10:
2950                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951                 break;
2952         case RENDERPATH_D3D11:
2953                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2954                 break;
2955         case RENDERPATH_GL20:
2956         case RENDERPATH_GLES2:
2957                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2958                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2959                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
2960                 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);
2961                 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);
2962                 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);
2963                 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]);
2964                 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]);
2965                 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));
2966                 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]);
2967                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
2968
2969                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
2970                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
2971                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
2973                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
2974                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
2975                 break;
2976         case RENDERPATH_GL11:
2977         case RENDERPATH_GL13:
2978         case RENDERPATH_GLES1:
2979                 break;
2980         case RENDERPATH_SOFT:
2981                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2982                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2983                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
2984                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
2985                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
2986                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2987                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2988                 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]);
2989                 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));
2990                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2991                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2992
2993                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
2994                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
2995                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
2996                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
2997                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
2998                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
2999                 break;
3000         }
3001 }
3002
3003 #define SKINFRAME_HASH 1024
3004
3005 typedef struct
3006 {
3007         int loadsequence; // incremented each level change
3008         memexpandablearray_t array;
3009         skinframe_t *hash[SKINFRAME_HASH];
3010 }
3011 r_skinframe_t;
3012 r_skinframe_t r_skinframe;
3013
3014 void R_SkinFrame_PrepareForPurge(void)
3015 {
3016         r_skinframe.loadsequence++;
3017         // wrap it without hitting zero
3018         if (r_skinframe.loadsequence >= 200)
3019                 r_skinframe.loadsequence = 1;
3020 }
3021
3022 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 {
3024         if (!skinframe)
3025                 return;
3026         // mark the skinframe as used for the purging code
3027         skinframe->loadsequence = r_skinframe.loadsequence;
3028 }
3029
3030 void R_SkinFrame_Purge(void)
3031 {
3032         int i;
3033         skinframe_t *s;
3034         for (i = 0;i < SKINFRAME_HASH;i++)
3035         {
3036                 for (s = r_skinframe.hash[i];s;s = s->next)
3037                 {
3038                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3039                         {
3040                                 if (s->merged == s->base)
3041                                         s->merged = NULL;
3042                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3043                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3044                                 R_PurgeTexture(s->merged);s->merged = NULL;
3045                                 R_PurgeTexture(s->base  );s->base   = NULL;
3046                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3047                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3048                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3049                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3050                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3051                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3052                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3053                                 s->loadsequence = 0;
3054                         }
3055                 }
3056         }
3057 }
3058
3059 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3060         skinframe_t *item;
3061         char basename[MAX_QPATH];
3062
3063         Image_StripImageExtension(name, basename, sizeof(basename));
3064
3065         if( last == NULL ) {
3066                 int hashindex;
3067                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068                 item = r_skinframe.hash[hashindex];
3069         } else {
3070                 item = last->next;
3071         }
3072
3073         // linearly search through the hash bucket
3074         for( ; item ; item = item->next ) {
3075                 if( !strcmp( item->basename, basename ) ) {
3076                         return item;
3077                 }
3078         }
3079         return NULL;
3080 }
3081
3082 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 {
3084         skinframe_t *item;
3085         int hashindex;
3086         char basename[MAX_QPATH];
3087
3088         Image_StripImageExtension(name, basename, sizeof(basename));
3089
3090         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3091         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3092                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093                         break;
3094
3095         if (!item) {
3096                 rtexture_t *dyntexture;
3097                 // check whether its a dynamic texture
3098                 dyntexture = CL_GetDynTexture( basename );
3099                 if (!add && !dyntexture)
3100                         return NULL;
3101                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3102                 memset(item, 0, sizeof(*item));
3103                 strlcpy(item->basename, basename, sizeof(item->basename));
3104                 item->base = dyntexture; // either NULL or dyntexture handle
3105                 item->textureflags = textureflags;
3106                 item->comparewidth = comparewidth;
3107                 item->compareheight = compareheight;
3108                 item->comparecrc = comparecrc;
3109                 item->next = r_skinframe.hash[hashindex];
3110                 r_skinframe.hash[hashindex] = item;
3111         }
3112         else if( item->base == NULL )
3113         {
3114                 rtexture_t *dyntexture;
3115                 // check whether its a dynamic texture
3116                 // 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]
3117                 dyntexture = CL_GetDynTexture( basename );
3118                 item->base = dyntexture; // either NULL or dyntexture handle
3119         }
3120
3121         R_SkinFrame_MarkUsed(item);
3122         return item;
3123 }
3124
3125 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3126         { \
3127                 unsigned long long avgcolor[5], wsum; \
3128                 int pix, comp, w; \
3129                 avgcolor[0] = 0; \
3130                 avgcolor[1] = 0; \
3131                 avgcolor[2] = 0; \
3132                 avgcolor[3] = 0; \
3133                 avgcolor[4] = 0; \
3134                 wsum = 0; \
3135                 for(pix = 0; pix < cnt; ++pix) \
3136                 { \
3137                         w = 0; \
3138                         for(comp = 0; comp < 3; ++comp) \
3139                                 w += getpixel; \
3140                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3141                         { \
3142                                 ++wsum; \
3143                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3144                                 w = getpixel; \
3145                                 for(comp = 0; comp < 3; ++comp) \
3146                                         avgcolor[comp] += getpixel * w; \
3147                                 avgcolor[3] += w; \
3148                         } \
3149                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3150                         avgcolor[4] += getpixel; \
3151                 } \
3152                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3153                         avgcolor[3] = 1; \
3154                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3155                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3156                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3157                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3158         }
3159
3160 extern cvar_t gl_picmip;
3161 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3162 {
3163         int j;
3164         unsigned char *pixels;
3165         unsigned char *bumppixels;
3166         unsigned char *basepixels = NULL;
3167         int basepixels_width = 0;
3168         int basepixels_height = 0;
3169         skinframe_t *skinframe;
3170         rtexture_t *ddsbase = NULL;
3171         qboolean ddshasalpha = false;
3172         float ddsavgcolor[4];
3173         char basename[MAX_QPATH];
3174         int miplevel = R_PicmipForFlags(textureflags);
3175         int savemiplevel = miplevel;
3176         int mymiplevel;
3177
3178         if (cls.state == ca_dedicated)
3179                 return NULL;
3180
3181         // return an existing skinframe if already loaded
3182         // if loading of the first image fails, don't make a new skinframe as it
3183         // would cause all future lookups of this to be missing
3184         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3185         if (skinframe && skinframe->base)
3186                 return skinframe;
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         // check for DDS texture file first
3191         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3192         {
3193                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3194                 if (basepixels == NULL)
3195                         return NULL;
3196         }
3197
3198         // FIXME handle miplevel
3199
3200         if (developer_loading.integer)
3201                 Con_Printf("loading skin \"%s\"\n", name);
3202
3203         // we've got some pixels to store, so really allocate this new texture now
3204         if (!skinframe)
3205                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3206         skinframe->stain = NULL;
3207         skinframe->merged = NULL;
3208         skinframe->base = NULL;
3209         skinframe->pants = NULL;
3210         skinframe->shirt = NULL;
3211         skinframe->nmap = NULL;
3212         skinframe->gloss = NULL;
3213         skinframe->glow = NULL;
3214         skinframe->fog = NULL;
3215         skinframe->reflect = NULL;
3216         skinframe->hasalpha = false;
3217
3218         if (ddsbase)
3219         {
3220                 skinframe->base = ddsbase;
3221                 skinframe->hasalpha = ddshasalpha;
3222                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3223                 if (r_loadfog && skinframe->hasalpha)
3224                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3225                 //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]);
3226         }
3227         else
3228         {
3229                 basepixels_width = image_width;
3230                 basepixels_height = image_height;
3231                 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);
3232                 if (textureflags & TEXF_ALPHA)
3233                 {
3234                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3235                         {
3236                                 if (basepixels[j] < 255)
3237                                 {
3238                                         skinframe->hasalpha = true;
3239                                         break;
3240                                 }
3241                         }
3242                         if (r_loadfog && skinframe->hasalpha)
3243                         {
3244                                 // has transparent pixels
3245                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3246                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3247                                 {
3248                                         pixels[j+0] = 255;
3249                                         pixels[j+1] = 255;
3250                                         pixels[j+2] = 255;
3251                                         pixels[j+3] = basepixels[j+3];
3252                                 }
3253                                 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);
3254                                 Mem_Free(pixels);
3255                         }
3256                 }
3257                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3258                 //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]);
3259                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3260                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3261                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3262                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3263         }
3264
3265         if (r_loaddds)
3266         {
3267                 mymiplevel = savemiplevel;
3268                 if (r_loadnormalmap)
3269                         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);
3270                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271                 if (r_loadgloss)
3272                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3273                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3274                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3276         }
3277
3278         // _norm is the name used by tenebrae and has been adopted as standard
3279         if (r_loadnormalmap && skinframe->nmap == NULL)
3280         {
3281                 mymiplevel = savemiplevel;
3282                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3283                 {
3284                         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);
3285                         Mem_Free(pixels);
3286                         pixels = NULL;
3287                 }
3288                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3289                 {
3290                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3291                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3292                         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);
3293                         Mem_Free(pixels);
3294                         Mem_Free(bumppixels);
3295                 }
3296                 else if (r_shadow_bumpscale_basetexture.value > 0)
3297                 {
3298                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3299                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3300                         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);
3301                         Mem_Free(pixels);
3302                 }
3303                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3304                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3305         }
3306
3307         // _luma is supported only for tenebrae compatibility
3308         // _glow is the preferred name
3309         mymiplevel = savemiplevel;
3310         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))))
3311         {
3312                 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);
3313                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3314                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3315                 Mem_Free(pixels);pixels = NULL;
3316         }
3317
3318         mymiplevel = savemiplevel;
3319         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3320         {
3321                 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);
3322                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3323                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3324                 Mem_Free(pixels);
3325                 pixels = NULL;
3326         }
3327
3328         mymiplevel = savemiplevel;
3329         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3330         {
3331                 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);
3332                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3333                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3334                 Mem_Free(pixels);
3335                 pixels = NULL;
3336         }
3337
3338         mymiplevel = savemiplevel;
3339         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3340         {
3341                 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);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3343                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3344                 Mem_Free(pixels);
3345                 pixels = NULL;
3346         }
3347
3348         mymiplevel = savemiplevel;
3349         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3350         {
3351                 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);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3353                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3354                 Mem_Free(pixels);
3355                 pixels = NULL;
3356         }
3357
3358         if (basepixels)
3359                 Mem_Free(basepixels);
3360
3361         return skinframe;
3362 }
3363
3364 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3365 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3366 {
3367         int i;
3368         unsigned char *temp1, *temp2;
3369         skinframe_t *skinframe;
3370
3371         if (cls.state == ca_dedicated)
3372                 return NULL;
3373
3374         // if already loaded just return it, otherwise make a new skinframe
3375         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3376         if (skinframe && skinframe->base)
3377                 return skinframe;
3378
3379         skinframe->stain = NULL;
3380         skinframe->merged = NULL;
3381         skinframe->base = NULL;
3382         skinframe->pants = NULL;
3383         skinframe->shirt = NULL;
3384         skinframe->nmap = NULL;
3385         skinframe->gloss = NULL;
3386         skinframe->glow = NULL;
3387         skinframe->fog = NULL;
3388         skinframe->reflect = NULL;
3389         skinframe->hasalpha = false;
3390
3391         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392         if (!skindata)
3393                 return NULL;
3394
3395         if (developer_loading.integer)
3396                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3397
3398         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3399         {
3400                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3401                 temp2 = temp1 + width * height * 4;
3402                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3403                 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);
3404                 Mem_Free(temp1);
3405         }
3406         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3407         if (textureflags & TEXF_ALPHA)
3408         {
3409                 for (i = 3;i < width * height * 4;i += 4)
3410                 {
3411                         if (skindata[i] < 255)
3412                         {
3413                                 skinframe->hasalpha = true;
3414                                 break;
3415                         }
3416                 }
3417                 if (r_loadfog && skinframe->hasalpha)
3418                 {
3419                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3420                         memcpy(fogpixels, skindata, width * height * 4);
3421                         for (i = 0;i < width * height * 4;i += 4)
3422                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3423                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3424                         Mem_Free(fogpixels);
3425                 }
3426         }
3427
3428         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3429         //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]);
3430
3431         return skinframe;
3432 }
3433
3434 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 {
3436         int i;
3437         int featuresmask;
3438         skinframe_t *skinframe;
3439
3440         if (cls.state == ca_dedicated)
3441                 return NULL;
3442
3443         // if already loaded just return it, otherwise make a new skinframe
3444         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3445         if (skinframe && skinframe->base)
3446                 return skinframe;
3447
3448         skinframe->stain = NULL;
3449         skinframe->merged = NULL;
3450         skinframe->base = NULL;
3451         skinframe->pants = NULL;
3452         skinframe->shirt = NULL;
3453         skinframe->nmap = NULL;
3454         skinframe->gloss = NULL;
3455         skinframe->glow = NULL;
3456         skinframe->fog = NULL;
3457         skinframe->reflect = NULL;
3458         skinframe->hasalpha = false;
3459
3460         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461         if (!skindata)
3462                 return NULL;
3463
3464         if (developer_loading.integer)
3465                 Con_Printf("loading quake skin \"%s\"\n", name);
3466
3467         // 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)
3468         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3469         memcpy(skinframe->qpixels, skindata, width*height);
3470         skinframe->qwidth = width;
3471         skinframe->qheight = height;
3472
3473         featuresmask = 0;
3474         for (i = 0;i < width * height;i++)
3475                 featuresmask |= palette_featureflags[skindata[i]];
3476
3477         skinframe->hasalpha = false;
3478         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3479         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3480         skinframe->qgeneratemerged = true;
3481         skinframe->qgeneratebase = skinframe->qhascolormapping;
3482         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3483
3484         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3485         //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]);
3486
3487         return skinframe;
3488 }
3489
3490 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 {
3492         int width;
3493         int height;
3494         unsigned char *skindata;
3495
3496         if (!skinframe->qpixels)
3497                 return;
3498
3499         if (!skinframe->qhascolormapping)
3500                 colormapped = false;
3501
3502         if (colormapped)
3503         {
3504                 if (!skinframe->qgeneratebase)
3505                         return;
3506         }
3507         else
3508         {
3509                 if (!skinframe->qgeneratemerged)
3510                         return;
3511         }
3512
3513         width = skinframe->qwidth;
3514         height = skinframe->qheight;
3515         skindata = skinframe->qpixels;
3516
3517         if (skinframe->qgeneratenmap)
3518         {
3519                 unsigned char *temp1, *temp2;
3520                 skinframe->qgeneratenmap = false;
3521                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3522                 temp2 = temp1 + width * height * 4;
3523                 // use either a custom palette or the quake palette
3524                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3525                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3526                 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);
3527                 Mem_Free(temp1);
3528         }
3529
3530         if (skinframe->qgenerateglow)
3531         {
3532                 skinframe->qgenerateglow = false;
3533                 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
3534         }
3535
3536         if (colormapped)
3537         {
3538                 skinframe->qgeneratebase = false;
3539                 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);
3540                 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);
3541                 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);
3542         }
3543         else
3544         {
3545                 skinframe->qgeneratemerged = false;
3546                 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);
3547         }
3548
3549         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3550         {
3551                 Mem_Free(skinframe->qpixels);
3552                 skinframe->qpixels = NULL;
3553         }
3554 }
3555
3556 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)
3557 {
3558         int i;
3559         skinframe_t *skinframe;
3560
3561         if (cls.state == ca_dedicated)
3562                 return NULL;
3563
3564         // if already loaded just return it, otherwise make a new skinframe
3565         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3566         if (skinframe && skinframe->base)
3567                 return skinframe;
3568
3569         skinframe->stain = NULL;
3570         skinframe->merged = NULL;
3571         skinframe->base = NULL;
3572         skinframe->pants = NULL;
3573         skinframe->shirt = NULL;
3574         skinframe->nmap = NULL;
3575         skinframe->gloss = NULL;
3576         skinframe->glow = NULL;
3577         skinframe->fog = NULL;
3578         skinframe->reflect = NULL;
3579         skinframe->hasalpha = false;
3580
3581         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582         if (!skindata)
3583                 return NULL;
3584
3585         if (developer_loading.integer)
3586                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3587
3588         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3589         if (textureflags & TEXF_ALPHA)
3590         {
3591                 for (i = 0;i < width * height;i++)
3592                 {
3593                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3594                         {
3595                                 skinframe->hasalpha = true;
3596                                 break;
3597                         }
3598                 }
3599                 if (r_loadfog && skinframe->hasalpha)
3600                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3601         }
3602
3603         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3604         //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]);
3605
3606         return skinframe;
3607 }
3608
3609 skinframe_t *R_SkinFrame_LoadMissing(void)
3610 {
3611         skinframe_t *skinframe;
3612
3613         if (cls.state == ca_dedicated)
3614                 return NULL;
3615
3616         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3617         skinframe->stain = NULL;
3618         skinframe->merged = NULL;
3619         skinframe->base = NULL;
3620         skinframe->pants = NULL;
3621         skinframe->shirt = NULL;
3622         skinframe->nmap = NULL;
3623         skinframe->gloss = NULL;
3624         skinframe->glow = NULL;
3625         skinframe->fog = NULL;
3626         skinframe->reflect = NULL;
3627         skinframe->hasalpha = false;
3628
3629         skinframe->avgcolor[0] = rand() / RAND_MAX;
3630         skinframe->avgcolor[1] = rand() / RAND_MAX;
3631         skinframe->avgcolor[2] = rand() / RAND_MAX;
3632         skinframe->avgcolor[3] = 1;
3633
3634         return skinframe;
3635 }
3636
3637 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3638 typedef struct suffixinfo_s
3639 {
3640         const char *suffix;
3641         qboolean flipx, flipy, flipdiagonal;
3642 }
3643 suffixinfo_t;
3644 static suffixinfo_t suffix[3][6] =
3645 {
3646         {
3647                 {"px",   false, false, false},
3648                 {"nx",   false, false, false},
3649                 {"py",   false, false, false},
3650                 {"ny",   false, false, false},
3651                 {"pz",   false, false, false},
3652                 {"nz",   false, false, false}
3653         },
3654         {
3655                 {"posx", false, false, false},
3656                 {"negx", false, false, false},
3657                 {"posy", false, false, false},
3658                 {"negy", false, false, false},
3659                 {"posz", false, false, false},
3660                 {"negz", false, false, false}
3661         },
3662         {
3663                 {"rt",    true, false,  true},
3664                 {"lf",   false,  true,  true},
3665                 {"ft",    true,  true, false},
3666                 {"bk",   false, false, false},
3667                 {"up",    true, false,  true},
3668                 {"dn",    true, false,  true}
3669         }
3670 };
3671
3672 static int componentorder[4] = {0, 1, 2, 3};
3673
3674 rtexture_t *R_LoadCubemap(const char *basename)
3675 {
3676         int i, j, cubemapsize;
3677         unsigned char *cubemappixels, *image_buffer;
3678         rtexture_t *cubemaptexture;
3679         char name[256];
3680         // must start 0 so the first loadimagepixels has no requested width/height
3681         cubemapsize = 0;
3682         cubemappixels = NULL;
3683         cubemaptexture = NULL;
3684         // keep trying different suffix groups (posx, px, rt) until one loads
3685         for (j = 0;j < 3 && !cubemappixels;j++)
3686         {
3687                 // load the 6 images in the suffix group
3688                 for (i = 0;i < 6;i++)
3689                 {
3690                         // generate an image name based on the base and and suffix
3691                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3692                         // load it
3693                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3694                         {
3695                                 // an image loaded, make sure width and height are equal
3696                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3697                                 {
3698                                         // if this is the first image to load successfully, allocate the cubemap memory
3699                                         if (!cubemappixels && image_width >= 1)
3700                                         {
3701                                                 cubemapsize = image_width;
3702                                                 // note this clears to black, so unavailable sides are black
3703                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3704                                         }
3705                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3706                                         if (cubemappixels)
3707                                                 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);
3708                                 }
3709                                 else
3710                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3711                                 // free the image
3712                                 Mem_Free(image_buffer);
3713                         }
3714                 }
3715         }
3716         // if a cubemap loaded, upload it
3717         if (cubemappixels)
3718         {
3719                 if (developer_loading.integer)
3720                         Con_Printf("loading cubemap \"%s\"\n", basename);
3721
3722                 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);
3723                 Mem_Free(cubemappixels);
3724         }
3725         else
3726         {
3727                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3728                 if (developer_loading.integer)
3729                 {
3730                         Con_Printf("(tried tried images ");
3731                         for (j = 0;j < 3;j++)
3732                                 for (i = 0;i < 6;i++)
3733                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3734                         Con_Print(" and was unable to find any of them).\n");
3735                 }
3736         }
3737         return cubemaptexture;
3738 }
3739
3740 rtexture_t *R_GetCubemap(const char *basename)
3741 {
3742         int i;
3743         for (i = 0;i < r_texture_numcubemaps;i++)
3744                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3745                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3746         if (i >= MAX_CUBEMAPS)
3747                 return r_texture_whitecube;
3748         r_texture_numcubemaps++;
3749         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3750         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3751         return r_texture_cubemaps[i].texture;
3752 }
3753
3754 void R_FreeCubemaps(void)
3755 {
3756         int i;
3757         for (i = 0;i < r_texture_numcubemaps;i++)
3758         {
3759                 if (developer_loading.integer)
3760                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3761                 if (r_texture_cubemaps[i].texture)
3762                         R_FreeTexture(r_texture_cubemaps[i].texture);
3763         }
3764         r_texture_numcubemaps = 0;
3765 }
3766
3767 void R_Main_FreeViewCache(void)
3768 {
3769         if (r_refdef.viewcache.entityvisible)
3770                 Mem_Free(r_refdef.viewcache.entityvisible);
3771         if (r_refdef.viewcache.world_pvsbits)
3772                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3773         if (r_refdef.viewcache.world_leafvisible)
3774                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3775         if (r_refdef.viewcache.world_surfacevisible)
3776                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3777         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3778 }
3779
3780 void R_Main_ResizeViewCache(void)
3781 {
3782         int numentities = r_refdef.scene.numentities;
3783         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3784         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3785         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3786         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3787         if (r_refdef.viewcache.maxentities < numentities)
3788         {
3789                 r_refdef.viewcache.maxentities = numentities;
3790                 if (r_refdef.viewcache.entityvisible)
3791                         Mem_Free(r_refdef.viewcache.entityvisible);
3792                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3793         }
3794         if (r_refdef.viewcache.world_numclusters != numclusters)
3795         {
3796                 r_refdef.viewcache.world_numclusters = numclusters;
3797                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3798                 if (r_refdef.viewcache.world_pvsbits)
3799                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3800                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3801         }
3802         if (r_refdef.viewcache.world_numleafs != numleafs)
3803         {
3804                 r_refdef.viewcache.world_numleafs = numleafs;
3805                 if (r_refdef.viewcache.world_leafvisible)
3806                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3807                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3808         }
3809         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3810         {
3811                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3812                 if (r_refdef.viewcache.world_surfacevisible)
3813                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3814                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3815         }
3816 }
3817
3818 extern rtexture_t *loadingscreentexture;
3819 void gl_main_start(void)
3820 {
3821         loadingscreentexture = NULL;
3822         r_texture_blanknormalmap = NULL;
3823         r_texture_white = NULL;
3824         r_texture_grey128 = NULL;
3825         r_texture_black = NULL;
3826         r_texture_whitecube = NULL;
3827         r_texture_normalizationcube = NULL;
3828         r_texture_fogattenuation = NULL;
3829         r_texture_fogheighttexture = NULL;
3830         r_texture_gammaramps = NULL;
3831         r_texture_numcubemaps = 0;
3832
3833         r_loaddds = r_texture_dds_load.integer != 0;
3834         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3835
3836         switch(vid.renderpath)
3837         {
3838         case RENDERPATH_GL20:
3839         case RENDERPATH_D3D9:
3840         case RENDERPATH_D3D10:
3841         case RENDERPATH_D3D11:
3842         case RENDERPATH_SOFT:
3843         case RENDERPATH_GLES2:
3844                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3845                 Cvar_SetValueQuick(&gl_combine, 1);
3846                 Cvar_SetValueQuick(&r_glsl, 1);
3847                 r_loadnormalmap = true;
3848                 r_loadgloss = true;
3849                 r_loadfog = false;
3850                 break;
3851         case RENDERPATH_GL13:
3852         case RENDERPATH_GLES1:
3853                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3854                 Cvar_SetValueQuick(&gl_combine, 1);
3855                 Cvar_SetValueQuick(&r_glsl, 0);
3856                 r_loadnormalmap = false;
3857                 r_loadgloss = false;
3858                 r_loadfog = true;
3859                 break;
3860         case RENDERPATH_GL11:
3861                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3862                 Cvar_SetValueQuick(&gl_combine, 0);
3863                 Cvar_SetValueQuick(&r_glsl, 0);
3864                 r_loadnormalmap = false;
3865                 r_loadgloss = false;
3866                 r_loadfog = true;
3867                 break;
3868         }
3869
3870         R_AnimCache_Free();
3871         R_FrameData_Reset();
3872
3873         r_numqueries = 0;
3874         r_maxqueries = 0;
3875         memset(r_queries, 0, sizeof(r_queries));
3876
3877         r_qwskincache = NULL;
3878         r_qwskincache_size = 0;
3879
3880         // due to caching of texture_t references, the collision cache must be reset
3881         Collision_Cache_Reset(true);
3882
3883         // set up r_skinframe loading system for textures
3884         memset(&r_skinframe, 0, sizeof(r_skinframe));
3885         r_skinframe.loadsequence = 1;
3886         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3887
3888         r_main_texturepool = R_AllocTexturePool();
3889         R_BuildBlankTextures();
3890         R_BuildNoTexture();
3891         if (vid.support.arb_texture_cube_map)
3892         {
3893                 R_BuildWhiteCube();
3894                 R_BuildNormalizationCube();
3895         }
3896         r_texture_fogattenuation = NULL;
3897         r_texture_fogheighttexture = NULL;
3898         r_texture_gammaramps = NULL;
3899         //r_texture_fogintensity = NULL;
3900         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3901         memset(&r_waterstate, 0, sizeof(r_waterstate));
3902         r_glsl_permutation = NULL;
3903         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3904         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3905         glslshaderstring = NULL;
3906 #ifdef SUPPORTD3D
3907         r_hlsl_permutation = NULL;
3908         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3909         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3910 #endif
3911         hlslshaderstring = NULL;
3912         memset(&r_svbsp, 0, sizeof (r_svbsp));
3913
3914         r_refdef.fogmasktable_density = 0;
3915 }
3916
3917 void gl_main_shutdown(void)
3918 {
3919         R_AnimCache_Free();
3920         R_FrameData_Reset();
3921
3922         R_Main_FreeViewCache();
3923
3924         switch(vid.renderpath)
3925         {
3926         case RENDERPATH_GL11:
3927         case RENDERPATH_GL13:
3928         case RENDERPATH_GL20:
3929         case RENDERPATH_GLES1:
3930         case RENDERPATH_GLES2:
3931                 if (r_maxqueries)
3932                         qglDeleteQueriesARB(r_maxqueries, r_queries);
3933                 break;
3934         case RENDERPATH_D3D9:
3935                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3936                 break;
3937         case RENDERPATH_D3D10:
3938                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3939                 break;
3940         case RENDERPATH_D3D11:
3941                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3942                 break;
3943         case RENDERPATH_SOFT:
3944                 break;
3945         }
3946
3947         r_numqueries = 0;
3948         r_maxqueries = 0;
3949         memset(r_queries, 0, sizeof(r_queries));
3950
3951         r_qwskincache = NULL;
3952         r_qwskincache_size = 0;
3953
3954         // clear out the r_skinframe state
3955         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3956         memset(&r_skinframe, 0, sizeof(r_skinframe));
3957
3958         if (r_svbsp.nodes)
3959                 Mem_Free(r_svbsp.nodes);
3960         memset(&r_svbsp, 0, sizeof (r_svbsp));
3961         R_FreeTexturePool(&r_main_texturepool);
3962         loadingscreentexture = NULL;
3963         r_texture_blanknormalmap = NULL;
3964         r_texture_white = NULL;
3965         r_texture_grey128 = NULL;
3966         r_texture_black = NULL;
3967         r_texture_whitecube = NULL;
3968         r_texture_normalizationcube = NULL;
3969         r_texture_fogattenuation = NULL;
3970         r_texture_fogheighttexture = NULL;
3971         r_texture_gammaramps = NULL;
3972         r_texture_numcubemaps = 0;
3973         //r_texture_fogintensity = NULL;
3974         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3975         memset(&r_waterstate, 0, sizeof(r_waterstate));
3976         R_GLSL_Restart_f();
3977
3978         r_glsl_permutation = NULL;
3979         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3980         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3981         glslshaderstring = NULL;
3982 #ifdef SUPPORTD3D
3983         r_hlsl_permutation = NULL;
3984         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3985         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3986 #endif
3987         hlslshaderstring = NULL;
3988 }
3989
3990 extern void CL_ParseEntityLump(char *entitystring);
3991 void gl_main_newmap(void)
3992 {
3993         // FIXME: move this code to client
3994         char *entities, entname[MAX_QPATH];
3995         if (r_qwskincache)
3996                 Mem_Free(r_qwskincache);
3997         r_qwskincache = NULL;
3998         r_qwskincache_size = 0;
3999         if (cl.worldmodel)
4000         {
4001                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4002                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4003                 {
4004                         CL_ParseEntityLump(entities);
4005                         Mem_Free(entities);
4006                         return;
4007                 }
4008                 if (cl.worldmodel->brush.entities)
4009                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4010         }
4011         R_Main_FreeViewCache();
4012
4013         R_FrameData_Reset();
4014 }
4015
4016 void GL_Main_Init(void)
4017 {
4018         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4019
4020         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4021         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4022         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4023         if (gamemode == GAME_NEHAHRA)
4024         {
4025                 Cvar_RegisterVariable (&gl_fogenable);
4026                 Cvar_RegisterVariable (&gl_fogdensity);
4027                 Cvar_RegisterVariable (&gl_fogred);
4028                 Cvar_RegisterVariable (&gl_foggreen);
4029                 Cvar_RegisterVariable (&gl_fogblue);
4030                 Cvar_RegisterVariable (&gl_fogstart);
4031                 Cvar_RegisterVariable (&gl_fogend);
4032                 Cvar_RegisterVariable (&gl_skyclip);
4033         }
4034         Cvar_RegisterVariable(&r_motionblur);
4035         Cvar_RegisterVariable(&r_motionblur_maxblur);
4036         Cvar_RegisterVariable(&r_motionblur_bmin);
4037         Cvar_RegisterVariable(&r_motionblur_vmin);
4038         Cvar_RegisterVariable(&r_motionblur_vmax);
4039         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4040         Cvar_RegisterVariable(&r_motionblur_randomize);
4041         Cvar_RegisterVariable(&r_damageblur);
4042         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4043         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4044         Cvar_RegisterVariable(&r_equalize_entities_by);
4045         Cvar_RegisterVariable(&r_equalize_entities_to);
4046         Cvar_RegisterVariable(&r_depthfirst);
4047         Cvar_RegisterVariable(&r_useinfinitefarclip);
4048         Cvar_RegisterVariable(&r_farclip_base);
4049         Cvar_RegisterVariable(&r_farclip_world);
4050         Cvar_RegisterVariable(&r_nearclip);
4051         Cvar_RegisterVariable(&r_deformvertexes);
4052         Cvar_RegisterVariable(&r_transparent);
4053         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4054         Cvar_RegisterVariable(&r_showoverdraw);
4055         Cvar_RegisterVariable(&r_showbboxes);
4056         Cvar_RegisterVariable(&r_showsurfaces);
4057         Cvar_RegisterVariable(&r_showtris);
4058         Cvar_RegisterVariable(&r_shownormals);
4059         Cvar_RegisterVariable(&r_showlighting);
4060         Cvar_RegisterVariable(&r_showshadowvolumes);
4061         Cvar_RegisterVariable(&r_showcollisionbrushes);
4062         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4063         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4064         Cvar_RegisterVariable(&r_showdisabledepthtest);
4065         Cvar_RegisterVariable(&r_drawportals);
4066         Cvar_RegisterVariable(&r_drawentities);
4067         Cvar_RegisterVariable(&r_draw2d);
4068         Cvar_RegisterVariable(&r_drawworld);
4069         Cvar_RegisterVariable(&r_cullentities_trace);
4070         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4071         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4072         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4073         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4074         Cvar_RegisterVariable(&r_drawviewmodel);
4075         Cvar_RegisterVariable(&r_drawexteriormodel);
4076         Cvar_RegisterVariable(&r_speeds);
4077         Cvar_RegisterVariable(&r_fullbrights);
4078         Cvar_RegisterVariable(&r_wateralpha);
4079         Cvar_RegisterVariable(&r_dynamic);
4080         Cvar_RegisterVariable(&r_fakelight);
4081         Cvar_RegisterVariable(&r_fakelight_intensity);
4082         Cvar_RegisterVariable(&r_fullbright);
4083         Cvar_RegisterVariable(&r_shadows);
4084         Cvar_RegisterVariable(&r_shadows_darken);
4085         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4086         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4087         Cvar_RegisterVariable(&r_shadows_throwdistance);
4088         Cvar_RegisterVariable(&r_shadows_throwdirection);
4089         Cvar_RegisterVariable(&r_shadows_focus);
4090         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4091         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4092         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4093         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4094         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4095         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4096         Cvar_RegisterVariable(&r_fog_exp2);
4097         Cvar_RegisterVariable(&r_fog_clear);
4098         Cvar_RegisterVariable(&r_drawfog);
4099         Cvar_RegisterVariable(&r_transparentdepthmasking);
4100         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4101         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4102         Cvar_RegisterVariable(&r_texture_dds_load);
4103         Cvar_RegisterVariable(&r_texture_dds_save);
4104         Cvar_RegisterVariable(&r_textureunits);
4105         Cvar_RegisterVariable(&gl_combine);
4106         Cvar_RegisterVariable(&r_viewfbo);
4107         Cvar_RegisterVariable(&r_viewscale);
4108         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4109         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4110         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4111         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4112         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4113         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4114         Cvar_RegisterVariable(&r_glsl);
4115         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4116         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4117         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4118         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4119         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4120         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4121         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4122         Cvar_RegisterVariable(&r_glsl_postprocess);
4123         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4124         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4125         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4126         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4127         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4128         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4129         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4130         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4131
4132         Cvar_RegisterVariable(&r_water);
4133         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4134         Cvar_RegisterVariable(&r_water_clippingplanebias);
4135         Cvar_RegisterVariable(&r_water_refractdistort);
4136         Cvar_RegisterVariable(&r_water_reflectdistort);
4137         Cvar_RegisterVariable(&r_water_scissormode);
4138         Cvar_RegisterVariable(&r_lerpsprites);
4139         Cvar_RegisterVariable(&r_lerpmodels);
4140         Cvar_RegisterVariable(&r_lerplightstyles);
4141         Cvar_RegisterVariable(&r_waterscroll);
4142         Cvar_RegisterVariable(&r_bloom);
4143         Cvar_RegisterVariable(&r_bloom_colorscale);
4144         Cvar_RegisterVariable(&r_bloom_brighten);
4145         Cvar_RegisterVariable(&r_bloom_blur);
4146         Cvar_RegisterVariable(&r_bloom_resolution);
4147         Cvar_RegisterVariable(&r_bloom_colorexponent);
4148         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4149         Cvar_RegisterVariable(&r_hdr);
4150         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4151         Cvar_RegisterVariable(&r_hdr_glowintensity);
4152         Cvar_RegisterVariable(&r_hdr_range);
4153         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4154         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4155         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4156         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4157         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4158         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4159         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4160         Cvar_RegisterVariable(&developer_texturelogging);
4161         Cvar_RegisterVariable(&gl_lightmaps);
4162         Cvar_RegisterVariable(&r_test);
4163         Cvar_RegisterVariable(&r_glsl_saturation);
4164         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4165         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4166         Cvar_RegisterVariable(&r_framedatasize);
4167         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4168                 Cvar_SetValue("r_fullbrights", 0);
4169         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4170
4171         Cvar_RegisterVariable(&r_track_sprites);
4172         Cvar_RegisterVariable(&r_track_sprites_flags);
4173         Cvar_RegisterVariable(&r_track_sprites_scalew);
4174         Cvar_RegisterVariable(&r_track_sprites_scaleh);
4175         Cvar_RegisterVariable(&r_overheadsprites_perspective);
4176         Cvar_RegisterVariable(&r_overheadsprites_pushback);
4177         Cvar_RegisterVariable(&r_overheadsprites_scalex);
4178         Cvar_RegisterVariable(&r_overheadsprites_scaley);
4179 }
4180
4181 extern void R_Textures_Init(void);
4182 extern void GL_Draw_Init(void);
4183 extern void GL_Main_Init(void);
4184 extern void R_Shadow_Init(void);
4185 extern void R_Sky_Init(void);
4186 extern void GL_Surf_Init(void);
4187 extern void R_Particles_Init(void);
4188 extern void R_Explosion_Init(void);
4189 extern void gl_backend_init(void);
4190 extern void Sbar_Init(void);
4191 extern void R_LightningBeams_Init(void);
4192 extern void Mod_RenderInit(void);
4193 extern void Font_Init(void);
4194
4195 void Render_Init(void)
4196 {
4197         gl_backend_init();
4198         R_Textures_Init();
4199         GL_Main_Init();
4200         Font_Init();
4201         GL_Draw_Init();
4202         R_Shadow_Init();
4203         R_Sky_Init();
4204         GL_Surf_Init();
4205         Sbar_Init();
4206         R_Particles_Init();
4207         R_Explosion_Init();
4208         R_LightningBeams_Init();
4209         Mod_RenderInit();
4210 }
4211
4212 /*
4213 ===============
4214 GL_Init
4215 ===============
4216 */
4217 extern char *ENGINE_EXTENSIONS;
4218 void GL_Init (void)
4219 {
4220         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4221         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4222         gl_version = (const char *)qglGetString(GL_VERSION);
4223         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4224
4225         if (!gl_extensions)
4226                 gl_extensions = "";
4227         if (!gl_platformextensions)
4228                 gl_platformextensions = "";
4229
4230         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4231         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4232         Con_Printf("GL_VERSION: %s\n", gl_version);
4233         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4234         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4235
4236         VID_CheckExtensions();
4237
4238         // LordHavoc: report supported extensions
4239         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4240
4241         // clear to black (loading plaque will be seen over this)
4242         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4243 }
4244
4245 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4246 {
4247         int i;
4248         mplane_t *p;
4249         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4250         {
4251                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4252                 if (i == 4)
4253                         continue;
4254                 p = r_refdef.view.frustum + i;
4255                 switch(p->signbits)
4256                 {
4257                 default:
4258                 case 0:
4259                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4260                                 return true;
4261                         break;
4262                 case 1:
4263                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4264                                 return true;
4265                         break;
4266                 case 2:
4267                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4268                                 return true;
4269                         break;
4270                 case 3:
4271                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4272                                 return true;
4273                         break;
4274                 case 4:
4275                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4276                                 return true;
4277                         break;
4278                 case 5:
4279                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4280                                 return true;
4281                         break;
4282                 case 6:
4283                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4284                                 return true;
4285                         break;
4286                 case 7:
4287                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4288                                 return true;
4289                         break;
4290                 }
4291         }
4292         return false;
4293 }
4294
4295 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4296 {
4297         int i;
4298         const mplane_t *p;
4299         for (i = 0;i < numplanes;i++)
4300         {
4301                 p = planes + i;
4302                 switch(p->signbits)
4303                 {
4304                 default:
4305                 case 0:
4306                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4307                                 return true;
4308                         break;
4309                 case 1:
4310                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4311                                 return true;
4312                         break;
4313                 case 2:
4314                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4315                                 return true;
4316                         break;
4317                 case 3:
4318                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4319                                 return true;
4320                         break;
4321                 case 4:
4322                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4323                                 return true;
4324                         break;
4325                 case 5:
4326                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4327                                 return true;
4328                         break;
4329                 case 6:
4330                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4331                                 return true;
4332                         break;
4333                 case 7:
4334                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4335                                 return true;
4336                         break;
4337                 }
4338         }
4339         return false;
4340 }
4341
4342 //==================================================================================
4343
4344 // LordHavoc: this stores temporary data used within the same frame
4345
4346 typedef struct r_framedata_mem_s
4347 {
4348         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4349         size_t size; // how much usable space
4350         size_t current; // how much space in use
4351         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4352         size_t wantedsize; // how much space was allocated
4353         unsigned char *data; // start of real data (16byte aligned)
4354 }
4355 r_framedata_mem_t;
4356
4357 static r_framedata_mem_t *r_framedata_mem;
4358
4359 void R_FrameData_Reset(void)
4360 {
4361         while (r_framedata_mem)
4362         {
4363                 r_framedata_mem_t *next = r_framedata_mem->purge;
4364                 Mem_Free(r_framedata_mem);
4365                 r_framedata_mem = next;
4366         }
4367 }
4368
4369 void R_FrameData_Resize(void)
4370 {
4371         size_t wantedsize;
4372         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4373         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4374         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4375         {
4376                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4377                 newmem->wantedsize = wantedsize;
4378                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4379                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4380                 newmem->current = 0;
4381                 newmem->mark = 0;
4382                 newmem->purge = r_framedata_mem;
4383                 r_framedata_mem = newmem;
4384         }
4385 }
4386
4387 void R_FrameData_NewFrame(void)
4388 {
4389         R_FrameData_Resize();
4390         if (!r_framedata_mem)
4391                 return;
4392         // if we ran out of space on the last frame, free the old memory now
4393         while (r_framedata_mem->purge)
4394         {
4395                 // repeatedly remove the second item in the list, leaving only head
4396                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4397                 Mem_Free(r_framedata_mem->purge);
4398                 r_framedata_mem->purge = next;
4399         }
4400         // reset the current mem pointer
4401         r_framedata_mem->current = 0;
4402         r_framedata_mem->mark = 0;
4403 }
4404
4405 void *R_FrameData_Alloc(size_t size)
4406 {
4407         void *data;
4408
4409         // align to 16 byte boundary - the data pointer is already aligned, so we
4410         // only need to ensure the size of every allocation is also aligned
4411         size = (size + 15) & ~15;
4412
4413         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4414         {
4415                 // emergency - we ran out of space, allocate more memory
4416                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4417                 R_FrameData_Resize();
4418         }
4419
4420         data = r_framedata_mem->data + r_framedata_mem->current;
4421         r_framedata_mem->current += size;
4422
4423         // count the usage for stats
4424         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4425         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4426
4427         return (void *)data;
4428 }
4429
4430 void *R_FrameData_Store(size_t size, void *data)
4431 {
4432         void *d = R_FrameData_Alloc(size);
4433         if (d && data)
4434                 memcpy(d, data, size);
4435         return d;
4436 }
4437
4438 void R_FrameData_SetMark(void)
4439 {
4440         if (!r_framedata_mem)
4441                 return;
4442         r_framedata_mem->mark = r_framedata_mem->current;
4443 }
4444
4445 void R_FrameData_ReturnToMark(void)
4446 {
4447         if (!r_framedata_mem)
4448                 return;
4449         r_framedata_mem->current = r_framedata_mem->mark;
4450 }
4451
4452 //==================================================================================
4453
4454 // LordHavoc: animcache originally written by Echon, rewritten since then
4455
4456 /**
4457  * Animation cache prevents re-generating mesh data for an animated model
4458  * multiple times in one frame for lighting, shadowing, reflections, etc.
4459  */
4460
4461 void R_AnimCache_Free(void)
4462 {
4463 }
4464
4465 void R_AnimCache_ClearCache(void)
4466 {
4467         int i;
4468         entity_render_t *ent;
4469
4470         for (i = 0;i < r_refdef.scene.numentities;i++)
4471         {
4472                 ent = r_refdef.scene.entities[i];
4473                 ent->animcache_vertex3f = NULL;
4474                 ent->animcache_normal3f = NULL;
4475                 ent->animcache_svector3f = NULL;
4476                 ent->animcache_tvector3f = NULL;
4477                 ent->animcache_vertexmesh = NULL;
4478                 ent->animcache_vertex3fbuffer = NULL;
4479                 ent->animcache_vertexmeshbuffer = NULL;
4480         }
4481 }
4482
4483 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4484 {
4485         int i;
4486
4487         // check if we need the meshbuffers
4488         if (!vid.useinterleavedarrays)
4489                 return;
4490
4491         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4492                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4493         // TODO: upload vertex3f buffer?
4494         if (ent->animcache_vertexmesh)
4495         {
4496                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4497                 for (i = 0;i < numvertices;i++)
4498                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4499                 if (ent->animcache_svector3f)
4500                         for (i = 0;i < numvertices;i++)
4501                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4502                 if (ent->animcache_tvector3f)
4503                         for (i = 0;i < numvertices;i++)
4504                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4505                 if (ent->animcache_normal3f)
4506                         for (i = 0;i < numvertices;i++)
4507                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4508                 // TODO: upload vertexmeshbuffer?
4509         }
4510 }
4511
4512 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4513 {
4514         dp_model_t *model = ent->model;
4515         int numvertices;
4516         // see if it's already cached this frame
4517         if (ent->animcache_vertex3f)
4518         {
4519                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4520                 if (wantnormals || wanttangents)
4521                 {
4522                         if (ent->animcache_normal3f)
4523                                 wantnormals = false;
4524                         if (ent->animcache_svector3f)
4525                                 wanttangents = false;
4526                         if (wantnormals || wanttangents)
4527                         {
4528                                 numvertices = model->surfmesh.num_vertices;
4529                                 if (wantnormals)
4530                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531                                 if (wanttangents)
4532                                 {
4533                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4534                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4535                                 }
4536                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4537                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4538                         }
4539                 }
4540         }
4541         else
4542         {
4543                 // see if this ent is worth caching
4544                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4545                         return false;
4546                 // get some memory for this entity and generate mesh data
4547                 numvertices = model->surfmesh.num_vertices;
4548                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549                 if (wantnormals)
4550                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551                 if (wanttangents)
4552                 {
4553                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4554                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4555                 }
4556                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4557                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4558         }
4559         return true;
4560 }
4561
4562 void R_AnimCache_CacheVisibleEntities(void)
4563 {
4564         int i;
4565         qboolean wantnormals = true;
4566         qboolean wanttangents = !r_showsurfaces.integer;
4567
4568         switch(vid.renderpath)
4569         {
4570         case RENDERPATH_GL20:
4571         case RENDERPATH_D3D9:
4572         case RENDERPATH_D3D10:
4573         case RENDERPATH_D3D11:
4574         case RENDERPATH_GLES2:
4575                 break;
4576         case RENDERPATH_GL11:
4577         case RENDERPATH_GL13:
4578         case RENDERPATH_GLES1:
4579                 wanttangents = false;
4580                 break;
4581         case RENDERPATH_SOFT:
4582                 break;
4583         }
4584
4585         if (r_shownormals.integer)
4586                 wanttangents = wantnormals = true;
4587
4588         // TODO: thread this
4589         // NOTE: R_PrepareRTLights() also caches entities
4590
4591         for (i = 0;i < r_refdef.scene.numentities;i++)
4592                 if (r_refdef.viewcache.entityvisible[i])
4593                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4594 }
4595
4596 //==================================================================================
4597
4598 static void R_View_UpdateEntityLighting (void)
4599 {
4600         int i;
4601         entity_render_t *ent;
4602         vec3_t tempdiffusenormal, avg;
4603         vec_t f, fa, fd, fdd;
4604         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4605
4606         for (i = 0;i < r_refdef.scene.numentities;i++)
4607         {
4608                 ent = r_refdef.scene.entities[i];
4609
4610                 // skip unseen models
4611                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4612                         continue;
4613
4614                 // skip bsp models
4615                 if (ent->model && ent->model->brush.num_leafs)
4616                 {
4617                         // TODO: use modellight for r_ambient settings on world?
4618                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4619                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4620                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4621                         continue;
4622                 }
4623
4624                 // fetch the lighting from the worldmodel data
4625                 VectorClear(ent->modellight_ambient);
4626                 VectorClear(ent->modellight_diffuse);
4627                 VectorClear(tempdiffusenormal);
4628                 if (ent->flags & RENDER_LIGHT)
4629                 {
4630                         vec3_t org;
4631                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4632
4633                         // complete lightning for lit sprites
4634                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4635                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4636                         {
4637                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4638                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4639                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4640                         }
4641                         else
4642                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4643
4644                         if(ent->flags & RENDER_EQUALIZE)
4645                         {
4646                                 // first fix up ambient lighting...
4647                                 if(r_equalize_entities_minambient.value > 0)
4648                                 {
4649                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4650                                         if(fd > 0)
4651                                         {
4652                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4653                                                 if(fa < r_equalize_entities_minambient.value * fd)
4654                                                 {
4655                                                         // solve:
4656                                                         //   fa'/fd' = minambient
4657                                                         //   fa'+0.25*fd' = fa+0.25*fd
4658                                                         //   ...
4659                                                         //   fa' = fd' * minambient
4660                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4661                                                         //   ...
4662                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4663                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4664                                                         //   ...
4665                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4666                                                         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
4667                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4668                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4669                                                 }
4670                                         }
4671                                 }
4672
4673                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4674                                 {
4675                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4676                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4677                                         f = fa + 0.25 * fd;
4678                                         if(f > 0)
4679                                         {
4680                                                 // adjust brightness and saturation to target
4681                                                 avg[0] = avg[1] = avg[2] = fa / f;
4682                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4683                                                 avg[0] = avg[1] = avg[2] = fd / f;
4684                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4685                                         }
4686                                 }
4687                         }
4688                 }
4689                 else // highly rare
4690                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4691
4692                 // move the light direction into modelspace coordinates for lighting code
4693                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4694                 if(VectorLength2(ent->modellight_lightdir) == 0)
4695                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4696                 VectorNormalize(ent->modellight_lightdir);
4697         }
4698 }
4699
4700 #define MAX_LINEOFSIGHTTRACES 64
4701
4702 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4703 {
4704         int i;
4705         vec3_t boxmins, boxmaxs;
4706         vec3_t start;
4707         vec3_t end;
4708         dp_model_t *model = r_refdef.scene.worldmodel;
4709
4710         if (!model || !model->brush.TraceLineOfSight)
4711                 return true;
4712
4713         // expand the box a little
4714         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4715         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4716         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4717         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4718         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4719         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4720
4721         // return true if eye is inside enlarged box
4722         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4723                 return true;
4724
4725         // try center
4726         VectorCopy(eye, start);
4727         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4728         if (model->brush.TraceLineOfSight(model, start, end))
4729                 return true;
4730
4731         // try various random positions
4732         for (i = 0;i < numsamples;i++)
4733         {
4734                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4735                 if (model->brush.TraceLineOfSight(model, start, end))
4736                         return true;
4737         }
4738
4739         return false;
4740 }
4741
4742
4743 static void R_View_UpdateEntityVisible (void)
4744 {
4745         int i;
4746         int renderimask;
4747         int samples;
4748         entity_render_t *ent;
4749
4750         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4751                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4752                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4753                 :                                                          RENDER_EXTERIORMODEL;
4754         if (!r_drawviewmodel.integer)
4755                 renderimask |= RENDER_VIEWMODEL;
4756         if (!r_drawexteriormodel.integer)
4757                 renderimask |= RENDER_EXTERIORMODEL;
4758         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4759         {
4760                 // worldmodel can check visibility
4761                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4762                 for (i = 0;i < r_refdef.scene.numentities;i++)
4763                 {
4764                         ent = r_refdef.scene.entities[i];
4765                         if (!(ent->flags & renderimask))
4766                         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)))
4767                         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))
4768                                 r_refdef.viewcache.entityvisible[i] = true;
4769                 }
4770         }
4771         else
4772         {
4773                 // no worldmodel or it can't check visibility
4774                 for (i = 0;i < r_refdef.scene.numentities;i++)
4775                 {
4776                         ent = r_refdef.scene.entities[i];
4777                         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));
4778                 }
4779         }
4780         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4781                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4782         {
4783                 for (i = 0;i < r_refdef.scene.numentities;i++)
4784                 {
4785                         if (!r_refdef.viewcache.entityvisible[i])
4786                                 continue;
4787                         ent = r_refdef.scene.entities[i];
4788                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4789                         {
4790                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4791                                 if (samples < 0)
4792                                         continue; // temp entities do pvs only
4793                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4794                                         ent->last_trace_visibility = realtime;
4795                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4796                                         r_refdef.viewcache.entityvisible[i] = 0;
4797                         }
4798                 }
4799         }
4800 }
4801
4802 /// only used if skyrendermasked, and normally returns false
4803 int R_DrawBrushModelsSky (void)
4804 {
4805         int i, sky;
4806         entity_render_t *ent;
4807
4808         sky = false;
4809         for (i = 0;i < r_refdef.scene.numentities;i++)
4810         {
4811                 if (!r_refdef.viewcache.entityvisible[i])
4812                         continue;
4813                 ent = r_refdef.scene.entities[i];
4814                 if (!ent->model || !ent->model->DrawSky)
4815                         continue;
4816                 ent->model->DrawSky(ent);
4817                 sky = true;
4818         }
4819         return sky;
4820 }
4821
4822 static void R_DrawNoModel(entity_render_t *ent);
4823 static void R_DrawModels(void)
4824 {
4825         int i;
4826         entity_render_t *ent;
4827
4828         for (i = 0;i < r_refdef.scene.numentities;i++)
4829         {
4830                 if (!r_refdef.viewcache.entityvisible[i])
4831                         continue;
4832                 ent = r_refdef.scene.entities[i];
4833                 r_refdef.stats.entities++;
4834                 /*
4835                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4836                 {
4837                         vec3_t f, l, u, o;
4838                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4839                         Con_Printf("R_DrawModels\n");
4840                         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]);
4841                         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);
4842                         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);
4843                 }
4844                 */
4845                 if (ent->model && ent->model->Draw != NULL)
4846                         ent->model->Draw(ent);
4847                 else
4848                         R_DrawNoModel(ent);
4849         }
4850 }
4851
4852 static void R_DrawModelsDepth(void)
4853 {
4854         int i;
4855         entity_render_t *ent;
4856
4857         for (i = 0;i < r_refdef.scene.numentities;i++)
4858         {
4859                 if (!r_refdef.viewcache.entityvisible[i])
4860                         continue;
4861                 ent = r_refdef.scene.entities[i];
4862                 if (ent->model && ent->model->DrawDepth != NULL)
4863                         ent->model->DrawDepth(ent);
4864         }
4865 }
4866
4867 static void R_DrawModelsDebug(void)
4868 {
4869         int i;
4870         entity_render_t *ent;
4871
4872         for (i = 0;i < r_refdef.scene.numentities;i++)
4873         {
4874                 if (!r_refdef.viewcache.entityvisible[i])
4875                         continue;
4876                 ent = r_refdef.scene.entities[i];
4877                 if (ent->model && ent->model->DrawDebug != NULL)
4878                         ent->model->DrawDebug(ent);
4879         }
4880 }
4881
4882 static void R_DrawModelsAddWaterPlanes(void)
4883 {
4884         int i;
4885         entity_render_t *ent;
4886
4887         for (i = 0;i < r_refdef.scene.numentities;i++)
4888         {
4889                 if (!r_refdef.viewcache.entityvisible[i])
4890                         continue;
4891                 ent = r_refdef.scene.entities[i];
4892                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4893                         ent->model->DrawAddWaterPlanes(ent);
4894         }
4895 }
4896
4897 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4898 {
4899         if (r_hdr_irisadaptation.integer)
4900         {
4901                 vec3_t ambient;
4902                 vec3_t diffuse;
4903                 vec3_t diffusenormal;
4904                 vec_t brightness;
4905                 vec_t goal;
4906                 vec_t adjust;
4907                 vec_t current;
4908                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4909                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4910                 brightness = max(0.0000001f, brightness);
4911                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4912                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4913                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4914                 current = r_hdr_irisadaptation_value.value;
4915                 if (current < goal)
4916                         current = min(current + adjust, goal);
4917                 else if (current > goal)
4918                         current = max(current - adjust, goal);
4919                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4920                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4921         }
4922         else if (r_hdr_irisadaptation_value.value != 1.0f)
4923                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4924 }
4925
4926 static void R_View_SetFrustum(const int *scissor)
4927 {
4928         int i;
4929         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4930         vec3_t forward, left, up, origin, v;
4931
4932         if(scissor)
4933         {
4934                 // flipped x coordinates (because x points left here)
4935                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4936                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4937
4938                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4939                 switch(vid.renderpath)
4940                 {
4941                         case RENDERPATH_D3D9:
4942                         case RENDERPATH_D3D10:
4943                         case RENDERPATH_D3D11:
4944                                 // non-flipped y coordinates
4945                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4946                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4947                                 break;
4948                         case RENDERPATH_SOFT:
4949                         case RENDERPATH_GL11:
4950                         case RENDERPATH_GL13:
4951                         case RENDERPATH_GL20:
4952                         case RENDERPATH_GLES1:
4953                         case RENDERPATH_GLES2:
4954                                 // non-flipped y coordinates
4955                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4956                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4957                                 break;
4958                 }
4959         }
4960
4961         // we can't trust r_refdef.view.forward and friends in reflected scenes
4962         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4963
4964 #if 0
4965         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4966         r_refdef.view.frustum[0].normal[1] = 0 - 0;
4967         r_refdef.view.frustum[0].normal[2] = -1 - 0;
4968         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4969         r_refdef.view.frustum[1].normal[1] = 0 + 0;
4970         r_refdef.view.frustum[1].normal[2] = -1 + 0;
4971         r_refdef.view.frustum[2].normal[0] = 0 - 0;
4972         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4973         r_refdef.view.frustum[2].normal[2] = -1 - 0;
4974         r_refdef.view.frustum[3].normal[0] = 0 + 0;
4975         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4976         r_refdef.view.frustum[3].normal[2] = -1 + 0;
4977 #endif
4978
4979 #if 0
4980         zNear = r_refdef.nearclip;
4981         nudge = 1.0 - 1.0 / (1<<23);
4982         r_refdef.view.frustum[4].normal[0] = 0 - 0;
4983         r_refdef.view.frustum[4].normal[1] = 0 - 0;
4984         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4985         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4986         r_refdef.view.frustum[5].normal[0] = 0 + 0;
4987         r_refdef.view.frustum[5].normal[1] = 0 + 0;
4988         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4989         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4990 #endif
4991
4992
4993
4994 #if 0
4995         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4996         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4997         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4998         r_refdef.view.frustum[0].dist = m[15] - m[12];
4999
5000         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5001         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5002         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5003         r_refdef.view.frustum[1].dist = m[15] + m[12];
5004
5005         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5006         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5007         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5008         r_refdef.view.frustum[2].dist = m[15] - m[13];
5009
5010         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5011         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5012         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5013         r_refdef.view.frustum[3].dist = m[15] + m[13];
5014
5015         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5016         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5017         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5018         r_refdef.view.frustum[4].dist = m[15] - m[14];
5019
5020         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5021         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5022         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5023         r_refdef.view.frustum[5].dist = m[15] + m[14];
5024 #endif
5025
5026         if (r_refdef.view.useperspective)
5027         {
5028                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5029                 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]);
5030                 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]);
5031                 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]);
5032                 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]);
5033
5034                 // then the normals from the corners relative to origin
5035                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5036                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5037                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5038                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5039
5040                 // in a NORMAL view, forward cross left == up
5041                 // in a REFLECTED view, forward cross left == down
5042                 // so our cross products above need to be adjusted for a left handed coordinate system
5043                 CrossProduct(forward, left, v);
5044                 if(DotProduct(v, up) < 0)
5045                 {
5046                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5047                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5048                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5049                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5050                 }
5051
5052                 // Leaving those out was a mistake, those were in the old code, and they
5053                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5054                 // I couldn't reproduce it after adding those normalizations. --blub
5055                 VectorNormalize(r_refdef.view.frustum[0].normal);
5056                 VectorNormalize(r_refdef.view.frustum[1].normal);
5057                 VectorNormalize(r_refdef.view.frustum[2].normal);
5058                 VectorNormalize(r_refdef.view.frustum[3].normal);
5059
5060                 // make the corners absolute
5061                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5062                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5063                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5064                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5065
5066                 // one more normal
5067                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5068
5069                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5070                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5071                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5072                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5073                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5074         }
5075         else
5076         {
5077                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5078                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5079                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5080                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5081                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5082                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5083                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5084                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5085                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5086                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5087         }
5088         r_refdef.view.numfrustumplanes = 5;
5089
5090         if (r_refdef.view.useclipplane)
5091         {
5092                 r_refdef.view.numfrustumplanes = 6;
5093                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5094         }
5095
5096         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5097                 PlaneClassify(r_refdef.view.frustum + i);
5098
5099         // LordHavoc: note to all quake engine coders, Quake had a special case
5100         // for 90 degrees which assumed a square view (wrong), so I removed it,
5101         // Quake2 has it disabled as well.
5102
5103         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5104         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5105         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5106         //PlaneClassify(&frustum[0]);
5107
5108         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5109         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5110         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5111         //PlaneClassify(&frustum[1]);
5112
5113         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5114         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5115         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5116         //PlaneClassify(&frustum[2]);
5117
5118         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5119         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5120         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5121         //PlaneClassify(&frustum[3]);
5122
5123         // nearclip plane
5124         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5125         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5126         //PlaneClassify(&frustum[4]);
5127 }
5128
5129 void R_View_UpdateWithScissor(const int *myscissor)
5130 {
5131         R_Main_ResizeViewCache();
5132         R_View_SetFrustum(myscissor);
5133         R_View_WorldVisibility(r_refdef.view.useclipplane);
5134         R_View_UpdateEntityVisible();
5135         R_View_UpdateEntityLighting();
5136 }
5137
5138 void R_View_Update(void)
5139 {
5140         R_Main_ResizeViewCache();
5141         R_View_SetFrustum(NULL);
5142         R_View_WorldVisibility(r_refdef.view.useclipplane);
5143         R_View_UpdateEntityVisible();
5144         R_View_UpdateEntityLighting();
5145 }
5146
5147 float viewscalefpsadjusted = 1.0f;
5148
5149 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5150 {
5151         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5152         scale = bound(0.03125f, scale, 1.0f);
5153         *outwidth = (int)ceil(width * scale);
5154         *outheight = (int)ceil(height * scale);
5155 }
5156
5157 void R_Mesh_SetMainRenderTargets(void)
5158 {
5159         if (r_bloomstate.fbo_framebuffer)
5160                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5161         else
5162                 R_Mesh_ResetRenderTargets();
5163 }
5164
5165 void R_SetupView(qboolean allowwaterclippingplane)
5166 {
5167         const float *customclipplane = NULL;
5168         float plane[4];
5169         int scaledwidth, scaledheight;
5170         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5171         {
5172                 // LordHavoc: couldn't figure out how to make this approach the
5173                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5174                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5175                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5176                         dist = r_refdef.view.clipplane.dist;
5177                 plane[0] = r_refdef.view.clipplane.normal[0];
5178                 plane[1] = r_refdef.view.clipplane.normal[1];
5179                 plane[2] = r_refdef.view.clipplane.normal[2];
5180                 plane[3] = -dist;
5181                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5182         }
5183
5184         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5185         if (!r_refdef.view.useperspective)
5186                 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);
5187         else if (vid.stencil && r_useinfinitefarclip.integer)
5188                 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);
5189         else
5190                 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);
5191         R_Mesh_SetMainRenderTargets();
5192         R_SetViewport(&r_refdef.view.viewport);
5193         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5194         {
5195                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5196                 float screenplane[4];
5197                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5198                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5199                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5200                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5201                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5202         }
5203 }
5204
5205 void R_EntityMatrix(const matrix4x4_t *matrix)
5206 {
5207         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5208         {
5209                 gl_modelmatrixchanged = false;
5210                 gl_modelmatrix = *matrix;
5211                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5212                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5213                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5214                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5215                 CHECKGLERROR
5216                 switch(vid.renderpath)
5217                 {
5218                 case RENDERPATH_D3D9:
5219 #ifdef SUPPORTD3D
5220                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5221                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5222 #endif
5223                         break;
5224                 case RENDERPATH_D3D10:
5225                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5226                         break;
5227                 case RENDERPATH_D3D11:
5228                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5229                         break;
5230                 case RENDERPATH_GL11:
5231                 case RENDERPATH_GL13:
5232                 case RENDERPATH_GLES1:
5233                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5234                         break;
5235                 case RENDERPATH_SOFT:
5236                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5237                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5238                         break;
5239                 case RENDERPATH_GL20:
5240                 case RENDERPATH_GLES2:
5241                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5242                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5243                         break;
5244                 }
5245         }
5246 }
5247
5248 void R_ResetViewRendering2D(void)
5249 {
5250         r_viewport_t viewport;
5251         DrawQ_Finish();
5252
5253         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5254         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);
5255         R_Mesh_ResetRenderTargets();
5256         R_SetViewport(&viewport);
5257         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5258         GL_Color(1, 1, 1, 1);
5259         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5260         GL_BlendFunc(GL_ONE, GL_ZERO);
5261         GL_ScissorTest(false);
5262         GL_DepthMask(false);
5263         GL_DepthRange(0, 1);
5264         GL_DepthTest(false);
5265         GL_DepthFunc(GL_LEQUAL);
5266         R_EntityMatrix(&identitymatrix);
5267         R_Mesh_ResetTextureState();
5268         GL_PolygonOffset(0, 0);
5269         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5270         switch(vid.renderpath)
5271         {
5272         case RENDERPATH_GL11:
5273         case RENDERPATH_GL13:
5274         case RENDERPATH_GL20:
5275         case RENDERPATH_GLES1:
5276         case RENDERPATH_GLES2:
5277                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5278                 break;
5279         case RENDERPATH_D3D9:
5280         case RENDERPATH_D3D10:
5281         case RENDERPATH_D3D11:
5282         case RENDERPATH_SOFT:
5283                 break;
5284         }
5285         GL_CullFace(GL_NONE);
5286 }
5287
5288 void R_ResetViewRendering3D(void)
5289 {
5290         DrawQ_Finish();
5291
5292         R_SetupView(true);
5293         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5294         GL_Color(1, 1, 1, 1);
5295         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5296         GL_BlendFunc(GL_ONE, GL_ZERO);
5297         GL_ScissorTest(true);
5298         GL_DepthMask(true);
5299         GL_DepthRange(0, 1);
5300         GL_DepthTest(true);
5301         GL_DepthFunc(GL_LEQUAL);
5302         R_EntityMatrix(&identitymatrix);
5303         R_Mesh_ResetTextureState();
5304         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5305         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5306         switch(vid.renderpath)
5307         {
5308         case RENDERPATH_GL11:
5309         case RENDERPATH_GL13:
5310         case RENDERPATH_GL20:
5311         case RENDERPATH_GLES1:
5312         case RENDERPATH_GLES2:
5313                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5314                 break;
5315         case RENDERPATH_D3D9:
5316         case RENDERPATH_D3D10:
5317         case RENDERPATH_D3D11:
5318         case RENDERPATH_SOFT:
5319                 break;
5320         }
5321         GL_CullFace(r_refdef.view.cullface_back);
5322 }
5323
5324 /*
5325 ================
5326 R_RenderView_UpdateViewVectors
5327 ================
5328 */
5329 static void R_RenderView_UpdateViewVectors(void)
5330 {
5331         // break apart the view matrix into vectors for various purposes
5332         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5333         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5334         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5335         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5336         // make an inverted copy of the view matrix for tracking sprites
5337         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5338 }
5339
5340 void R_RenderScene(void);
5341 void R_RenderWaterPlanes(void);
5342
5343 static void R_Water_StartFrame(void)
5344 {
5345         int i;
5346         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5347         r_waterstate_waterplane_t *p;
5348
5349         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5350                 return;
5351
5352         switch(vid.renderpath)
5353         {
5354         case RENDERPATH_GL20:
5355         case RENDERPATH_D3D9:
5356         case RENDERPATH_D3D10:
5357         case RENDERPATH_D3D11:
5358         case RENDERPATH_SOFT:
5359         case RENDERPATH_GLES2:
5360                 break;
5361         case RENDERPATH_GL11:
5362         case RENDERPATH_GL13:
5363         case RENDERPATH_GLES1:
5364                 return;
5365         }
5366
5367         // set waterwidth and waterheight to the water resolution that will be
5368         // used (often less than the screen resolution for faster rendering)
5369         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5370
5371         // calculate desired texture sizes
5372         // can't use water if the card does not support the texture size
5373         if (!r_water.integer || r_showsurfaces.integer)
5374                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5375         else if (vid.support.arb_texture_non_power_of_two)
5376         {
5377                 texturewidth = waterwidth;
5378                 textureheight = waterheight;
5379                 camerawidth = waterwidth;
5380                 cameraheight = waterheight;
5381         }
5382         else
5383         {
5384                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5385                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5386                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5387                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5388         }
5389
5390         // allocate textures as needed
5391         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5392         {
5393                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5394                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5395                 {
5396                         if (p->texture_refraction)
5397                                 R_FreeTexture(p->texture_refraction);
5398                         p->texture_refraction = NULL;
5399                         if (p->texture_reflection)
5400                                 R_FreeTexture(p->texture_reflection);
5401                         p->texture_reflection = NULL;
5402                         if (p->texture_camera)
5403                                 R_FreeTexture(p->texture_camera);
5404                         p->texture_camera = NULL;
5405                 }
5406                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5407                 r_waterstate.texturewidth = texturewidth;
5408                 r_waterstate.textureheight = textureheight;
5409                 r_waterstate.camerawidth = camerawidth;
5410                 r_waterstate.cameraheight = cameraheight;
5411         }
5412
5413         if (r_waterstate.texturewidth)
5414         {
5415                 int scaledwidth, scaledheight;
5416
5417                 r_waterstate.enabled = true;
5418
5419                 // when doing a reduced render (HDR) we want to use a smaller area
5420                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5421                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5422                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5423
5424                 // set up variables that will be used in shader setup
5425                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5426                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5427                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5428                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5429         }
5430
5431         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5432         r_waterstate.numwaterplanes = 0;
5433 }
5434
5435 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5436 {
5437         int triangleindex, planeindex;
5438         const int *e;
5439         vec3_t vert[3];
5440         vec3_t normal;
5441         vec3_t center;
5442         mplane_t plane;
5443         r_waterstate_waterplane_t *p;
5444         texture_t *t = R_GetCurrentTexture(surface->texture);
5445
5446         // just use the first triangle with a valid normal for any decisions
5447         VectorClear(normal);
5448         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5449         {
5450                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5451                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5452                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5453                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5454                 if (VectorLength2(normal) >= 0.001)
5455                         break;
5456         }
5457
5458         VectorCopy(normal, plane.normal);
5459         VectorNormalize(plane.normal);
5460         plane.dist = DotProduct(vert[0], plane.normal);
5461         PlaneClassify(&plane);
5462         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5463         {
5464                 // skip backfaces (except if nocullface is set)
5465                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5466                         return;
5467                 VectorNegate(plane.normal, plane.normal);
5468                 plane.dist *= -1;
5469                 PlaneClassify(&plane);
5470         }
5471
5472
5473         // find a matching plane if there is one
5474         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5475                 if(p->camera_entity == t->camera_entity)
5476                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5477                                 break;
5478         if (planeindex >= r_waterstate.maxwaterplanes)
5479                 return; // nothing we can do, out of planes
5480
5481         // if this triangle does not fit any known plane rendered this frame, add one
5482         if (planeindex >= r_waterstate.numwaterplanes)
5483         {
5484                 // store the new plane
5485                 r_waterstate.numwaterplanes++;
5486                 p->plane = plane;
5487                 // clear materialflags and pvs
5488                 p->materialflags = 0;
5489                 p->pvsvalid = false;
5490                 p->camera_entity = t->camera_entity;
5491                 VectorCopy(surface->mins, p->mins);
5492                 VectorCopy(surface->maxs, p->maxs);
5493         }
5494         else
5495         {
5496                 // merge mins/maxs
5497                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5498                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5499                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5500                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5501                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5502                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5503         }
5504         // merge this surface's materialflags into the waterplane
5505         p->materialflags |= t->currentmaterialflags;
5506         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5507         {
5508                 // merge this surface's PVS into the waterplane
5509                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5510                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5511                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5512                 {
5513                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5514                         p->pvsvalid = true;
5515                 }
5516         }
5517 }
5518
5519 static void R_Water_ProcessPlanes(void)
5520 {
5521         int myscissor[4];
5522         r_refdef_view_t originalview;
5523         r_refdef_view_t myview;
5524         int planeindex;
5525         r_waterstate_waterplane_t *p;
5526         vec3_t visorigin;
5527
5528         originalview = r_refdef.view;
5529
5530         // make sure enough textures are allocated
5531         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5532         {
5533                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5534                 {
5535                         if (!p->texture_refraction)
5536                                 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);
5537                         if (!p->texture_refraction)
5538                                 goto error;
5539                 }
5540                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5541                 {
5542                         if (!p->texture_camera)
5543                                 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);
5544                         if (!p->texture_camera)
5545                                 goto error;
5546                 }
5547
5548                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5549                 {
5550                         if (!p->texture_reflection)
5551                                 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);
5552                         if (!p->texture_reflection)
5553                                 goto error;
5554                 }
5555         }
5556
5557         // render views
5558         r_refdef.view = originalview;
5559         r_refdef.view.showdebug = false;
5560         r_refdef.view.width = r_waterstate.waterwidth;
5561         r_refdef.view.height = r_waterstate.waterheight;
5562         r_refdef.view.useclipplane = true;
5563         myview = r_refdef.view;
5564         r_waterstate.renderingscene = true;
5565         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5566         {
5567                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5568                 {
5569                         r_refdef.view = myview;
5570                         if(r_water_scissormode.integer)
5571                         {
5572                                 R_SetupView(true);
5573                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5575                         }
5576
5577                         // render reflected scene and copy into texture
5578                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5579                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5580                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5581                         r_refdef.view.clipplane = p->plane;
5582
5583                         // reverse the cullface settings for this render
5584                         r_refdef.view.cullface_front = GL_FRONT;
5585                         r_refdef.view.cullface_back = GL_BACK;
5586                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5587                         {
5588                                 r_refdef.view.usecustompvs = true;
5589                                 if (p->pvsvalid)
5590                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5591                                 else
5592                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5593                         }
5594
5595                         R_ResetViewRendering3D();
5596                         R_ClearScreen(r_refdef.fogenabled);
5597                         if(r_water_scissormode.integer & 2)
5598                                 R_View_UpdateWithScissor(myscissor);
5599                         else
5600                                 R_View_Update();
5601                         if(r_water_scissormode.integer & 1)
5602                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5603                         R_RenderScene();
5604
5605                         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);
5606                 }
5607
5608                 // render the normal view scene and copy into texture
5609                 // (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)
5610                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5611                 {
5612                         r_refdef.view = myview;
5613                         if(r_water_scissormode.integer)
5614                         {
5615                                 R_SetupView(true);
5616                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5617                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5618                         }
5619
5620                         r_waterstate.renderingrefraction = true;
5621
5622                         r_refdef.view.clipplane = p->plane;
5623                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5624                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5625
5626                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5627                         {
5628                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5629                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5630                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5631                                 R_RenderView_UpdateViewVectors();
5632                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5633                                 {
5634                                         r_refdef.view.usecustompvs = true;
5635                                         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);
5636                                 }
5637                         }
5638
5639                         PlaneClassify(&r_refdef.view.clipplane);
5640
5641                         R_ResetViewRendering3D();
5642                         R_ClearScreen(r_refdef.fogenabled);
5643                         if(r_water_scissormode.integer & 2)
5644                                 R_View_UpdateWithScissor(myscissor);
5645                         else
5646                                 R_View_Update();
5647                         if(r_water_scissormode.integer & 1)
5648                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5649                         R_RenderScene();
5650
5651                         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);
5652                         r_waterstate.renderingrefraction = false;
5653                 }
5654                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5655                 {
5656                         r_refdef.view = myview;
5657
5658                         r_refdef.view.clipplane = p->plane;
5659                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5661
5662                         r_refdef.view.width = r_waterstate.camerawidth;
5663                         r_refdef.view.height = r_waterstate.cameraheight;
5664                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5665                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5666
5667                         if(p->camera_entity)
5668                         {
5669                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5670                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5671                         }
5672
5673                         // note: all of the view is used for displaying... so
5674                         // there is no use in scissoring
5675
5676                         // reverse the cullface settings for this render
5677                         r_refdef.view.cullface_front = GL_FRONT;
5678                         r_refdef.view.cullface_back = GL_BACK;
5679                         // also reverse the view matrix
5680                         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
5681                         R_RenderView_UpdateViewVectors();
5682                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5683                         {
5684                                 r_refdef.view.usecustompvs = true;
5685                                 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);
5686                         }
5687                         
5688                         // camera needs no clipplane
5689                         r_refdef.view.useclipplane = false;
5690
5691                         PlaneClassify(&r_refdef.view.clipplane);
5692
5693                         R_ResetViewRendering3D();
5694                         R_ClearScreen(r_refdef.fogenabled);
5695                         R_View_Update();
5696                         R_RenderScene();
5697
5698                         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);
5699                         r_waterstate.renderingrefraction = false;
5700                 }
5701
5702         }
5703         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5704         r_waterstate.renderingscene = false;
5705         r_refdef.view = originalview;
5706         R_ResetViewRendering3D();
5707         R_ClearScreen(r_refdef.fogenabled);
5708         R_View_Update();
5709         return;
5710 error:
5711         r_refdef.view = originalview;
5712         r_waterstate.renderingscene = false;
5713         Cvar_SetValueQuick(&r_water, 0);
5714         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5715         return;
5716 }
5717
5718 void R_Bloom_StartFrame(void)
5719 {
5720         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5721         int viewwidth, viewheight;
5722         textype_t textype;
5723
5724         if (r_viewscale_fpsscaling.integer)
5725         {
5726                 double actualframetime;
5727                 double targetframetime;
5728                 double adjust;
5729                 actualframetime = r_refdef.lastdrawscreentime;
5730                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5731                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5732                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5733                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5734                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5735                 viewscalefpsadjusted += adjust;
5736                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5737         }
5738         else
5739                 viewscalefpsadjusted = 1.0f;
5740
5741         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5742
5743         switch(vid.renderpath)
5744         {
5745         case RENDERPATH_GL20:
5746         case RENDERPATH_D3D9:
5747         case RENDERPATH_D3D10:
5748         case RENDERPATH_D3D11:
5749         case RENDERPATH_SOFT:
5750         case RENDERPATH_GLES2:
5751                 break;
5752         case RENDERPATH_GL11:
5753         case RENDERPATH_GL13:
5754         case RENDERPATH_GLES1:
5755                 return;
5756         }
5757
5758         // set bloomwidth and bloomheight to the bloom resolution that will be
5759         // used (often less than the screen resolution for faster rendering)
5760         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5761         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5762         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5763         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5764         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5765
5766         // calculate desired texture sizes
5767         if (vid.support.arb_texture_non_power_of_two)
5768         {
5769                 screentexturewidth = vid.width;
5770                 screentextureheight = vid.height;
5771                 bloomtexturewidth = r_bloomstate.bloomwidth;
5772                 bloomtextureheight = r_bloomstate.bloomheight;
5773         }
5774         else
5775         {
5776                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5777                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5778                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5779                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5780         }
5781
5782         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))
5783         {
5784                 Cvar_SetValueQuick(&r_hdr, 0);
5785                 Cvar_SetValueQuick(&r_bloom, 0);
5786                 Cvar_SetValueQuick(&r_motionblur, 0);
5787                 Cvar_SetValueQuick(&r_damageblur, 0);
5788         }
5789
5790         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)
5791                 screentexturewidth = screentextureheight = 0;
5792         if (!r_hdr.integer && !r_bloom.integer)
5793                 bloomtexturewidth = bloomtextureheight = 0;
5794
5795         textype = TEXTYPE_COLORBUFFER;
5796         switch (vid.renderpath)
5797         {
5798         case RENDERPATH_GL20:
5799         case RENDERPATH_GLES2:
5800                 if (vid.support.ext_framebuffer_object)
5801                 {
5802                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5803                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5804                 }
5805                 break;
5806         case RENDERPATH_GL11:
5807         case RENDERPATH_GL13:
5808         case RENDERPATH_GLES1:
5809         case RENDERPATH_D3D9:
5810         case RENDERPATH_D3D10:
5811         case RENDERPATH_D3D11:
5812         case RENDERPATH_SOFT:
5813                 break;
5814         }
5815
5816         // allocate textures as needed
5817         if (r_bloomstate.screentexturewidth != screentexturewidth
5818          || r_bloomstate.screentextureheight != screentextureheight
5819          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5820          || r_bloomstate.bloomtextureheight != bloomtextureheight
5821          || r_bloomstate.texturetype != textype
5822          || r_bloomstate.viewfbo != r_viewfbo.integer)
5823         {
5824                 if (r_bloomstate.texture_bloom)
5825                         R_FreeTexture(r_bloomstate.texture_bloom);
5826                 r_bloomstate.texture_bloom = NULL;
5827                 if (r_bloomstate.texture_screen)
5828                         R_FreeTexture(r_bloomstate.texture_screen);
5829                 r_bloomstate.texture_screen = NULL;
5830                 if (r_bloomstate.fbo_framebuffer)
5831                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5832                 r_bloomstate.fbo_framebuffer = 0;
5833                 if (r_bloomstate.texture_framebuffercolor)
5834                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5835                 r_bloomstate.texture_framebuffercolor = NULL;
5836                 if (r_bloomstate.texture_framebufferdepth)
5837                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5838                 r_bloomstate.texture_framebufferdepth = NULL;
5839                 r_bloomstate.screentexturewidth = screentexturewidth;
5840                 r_bloomstate.screentextureheight = screentextureheight;
5841                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5842                         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);
5843                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5844                 {
5845                         // FIXME: choose depth bits based on a cvar
5846                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5847                         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);
5848                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5849                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5850                         // render depth into one texture and normalmap into the other
5851                         if (qglDrawBuffer)
5852                         {
5853                                 int status;
5854                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5855                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5856                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5857                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5858                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5859                         }
5860                 }
5861                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5862                 r_bloomstate.bloomtextureheight = bloomtextureheight;
5863                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5864                         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);
5865                 r_bloomstate.viewfbo = r_viewfbo.integer;
5866                 r_bloomstate.texturetype = textype;
5867         }
5868
5869         // when doing a reduced render (HDR) we want to use a smaller area
5870         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5871         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5872         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5873         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5874         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5875
5876         // set up a texcoord array for the full resolution screen image
5877         // (we have to keep this around to copy back during final render)
5878         r_bloomstate.screentexcoord2f[0] = 0;
5879         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5880         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5881         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
5882         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
5883         r_bloomstate.screentexcoord2f[5] = 0;
5884         r_bloomstate.screentexcoord2f[6] = 0;
5885         r_bloomstate.screentexcoord2f[7] = 0;
5886
5887         // set up a texcoord array for the reduced resolution bloom image
5888         // (which will be additive blended over the screen image)
5889         r_bloomstate.bloomtexcoord2f[0] = 0;
5890         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5892         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5893         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
5894         r_bloomstate.bloomtexcoord2f[5] = 0;
5895         r_bloomstate.bloomtexcoord2f[6] = 0;
5896         r_bloomstate.bloomtexcoord2f[7] = 0;
5897
5898         switch(vid.renderpath)
5899         {
5900         case RENDERPATH_GL11:
5901         case RENDERPATH_GL13:
5902         case RENDERPATH_GL20:
5903         case RENDERPATH_SOFT:
5904         case RENDERPATH_GLES1:
5905         case RENDERPATH_GLES2:
5906                 break;
5907         case RENDERPATH_D3D9:
5908         case RENDERPATH_D3D10:
5909         case RENDERPATH_D3D11:
5910                 {
5911                         int i;
5912                         for (i = 0;i < 4;i++)
5913                         {
5914                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5915                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5916                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5917                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5918                         }
5919                 }
5920                 break;
5921         }
5922
5923         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5924         {
5925                 r_bloomstate.enabled = true;
5926                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5927         }
5928
5929         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);
5930
5931         if (r_bloomstate.fbo_framebuffer)
5932                 r_refdef.view.clear = true;
5933 }
5934
5935 void R_Bloom_CopyBloomTexture(float colorscale)
5936 {
5937         r_refdef.stats.bloom++;
5938
5939         // scale down screen texture to the bloom texture size
5940         CHECKGLERROR
5941         R_Mesh_SetMainRenderTargets();
5942         R_SetViewport(&r_bloomstate.viewport);
5943         GL_BlendFunc(GL_ONE, GL_ZERO);
5944         GL_Color(colorscale, colorscale, colorscale, 1);
5945         // 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...
5946         switch(vid.renderpath)
5947         {
5948         case RENDERPATH_GL11:
5949         case RENDERPATH_GL13:
5950         case RENDERPATH_GL20:
5951         case RENDERPATH_GLES1:
5952         case RENDERPATH_GLES2:
5953         case RENDERPATH_SOFT:
5954                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5955                 break;
5956         case RENDERPATH_D3D9:
5957         case RENDERPATH_D3D10:
5958         case RENDERPATH_D3D11:
5959                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5960                 break;
5961         }
5962         // TODO: do boxfilter scale-down in shader?
5963         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5964         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5966
5967         // we now have a bloom image in the framebuffer
5968         // copy it into the bloom image texture for later processing
5969         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);
5970         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5971 }
5972
5973 void R_Bloom_CopyHDRTexture(void)
5974 {
5975         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);
5976         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5977 }
5978
5979 void R_Bloom_MakeTexture(void)
5980 {
5981         int x, range, dir;
5982         float xoffset, yoffset, r, brighten;
5983
5984         r_refdef.stats.bloom++;
5985
5986         R_ResetViewRendering2D();
5987
5988         // we have a bloom image in the framebuffer
5989         CHECKGLERROR
5990         R_SetViewport(&r_bloomstate.viewport);
5991
5992         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5993         {
5994                 x *= 2;
5995                 r = bound(0, r_bloom_colorexponent.value / x, 1);
5996                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5997                 GL_Color(r,r,r,1);
5998                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5999                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6000                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6002
6003                 // copy the vertically blurred bloom view to a texture
6004                 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);
6005                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6006         }
6007
6008         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6009         brighten = r_bloom_brighten.value;
6010         if (r_bloomstate.hdr)
6011                 brighten *= r_hdr_range.value;
6012         brighten = sqrt(brighten);
6013         if(range >= 1)
6014                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6015         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6016
6017         for (dir = 0;dir < 2;dir++)
6018         {
6019                 // blend on at multiple vertical offsets to achieve a vertical blur
6020                 // TODO: do offset blends using GLSL
6021                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6022                 GL_BlendFunc(GL_ONE, GL_ZERO);
6023                 for (x = -range;x <= range;x++)
6024                 {
6025                         if (!dir){xoffset = 0;yoffset = x;}
6026                         else {xoffset = x;yoffset = 0;}
6027                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6028                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6029                         // compute a texcoord array with the specified x and y offset
6030                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6031                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6034                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6035                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6036                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6037                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6038                         // this r value looks like a 'dot' particle, fading sharply to
6039                         // black at the edges
6040                         // (probably not realistic but looks good enough)
6041                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6042                         //r = brighten/(range*2+1);
6043                         r = brighten / (range * 2 + 1);
6044                         if(range >= 1)
6045                                 r *= (1 - x*x/(float)(range*range));
6046                         GL_Color(r, r, r, 1);
6047                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6048                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6049                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6050                         GL_BlendFunc(GL_ONE, GL_ONE);
6051                 }
6052
6053                 // copy the vertically blurred bloom view to a texture
6054                 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);
6055                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6056         }
6057 }
6058
6059 void R_HDR_RenderBloomTexture(void)
6060 {
6061         int oldwidth, oldheight;
6062         float oldcolorscale;
6063         qboolean oldwaterstate;
6064
6065         oldwaterstate = r_waterstate.enabled;
6066         oldcolorscale = r_refdef.view.colorscale;
6067         oldwidth = r_refdef.view.width;
6068         oldheight = r_refdef.view.height;
6069         r_refdef.view.width = r_bloomstate.bloomwidth;
6070         r_refdef.view.height = r_bloomstate.bloomheight;
6071
6072         if(r_hdr.integer < 2)
6073                 r_waterstate.enabled = false;
6074
6075         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6076         // TODO: add exposure compensation features
6077         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6078
6079         r_refdef.view.showdebug = false;
6080         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6081
6082         R_ResetViewRendering3D();
6083
6084         R_ClearScreen(r_refdef.fogenabled);
6085         if (r_timereport_active)
6086                 R_TimeReport("HDRclear");
6087
6088         R_View_Update();
6089         if (r_timereport_active)
6090                 R_TimeReport("visibility");
6091
6092         // only do secondary renders with HDR if r_hdr is 2 or higher
6093         r_waterstate.numwaterplanes = 0;
6094         if (r_waterstate.enabled)
6095                 R_RenderWaterPlanes();
6096
6097         r_refdef.view.showdebug = true;
6098         R_RenderScene();
6099         r_waterstate.numwaterplanes = 0;
6100
6101         R_ResetViewRendering2D();
6102
6103         R_Bloom_CopyHDRTexture();
6104         R_Bloom_MakeTexture();
6105
6106         // restore the view settings
6107         r_waterstate.enabled = oldwaterstate;
6108         r_refdef.view.width = oldwidth;
6109         r_refdef.view.height = oldheight;
6110         r_refdef.view.colorscale = oldcolorscale;
6111
6112         R_ResetViewRendering3D();
6113
6114         R_ClearScreen(r_refdef.fogenabled);
6115         if (r_timereport_active)
6116                 R_TimeReport("viewclear");
6117 }
6118
6119 static void R_BlendView(void)
6120 {
6121         unsigned int permutation;
6122         float uservecs[4][4];
6123
6124         switch (vid.renderpath)
6125         {
6126         case RENDERPATH_GL20:
6127         case RENDERPATH_D3D9:
6128         case RENDERPATH_D3D10:
6129         case RENDERPATH_D3D11:
6130         case RENDERPATH_SOFT:
6131         case RENDERPATH_GLES2:
6132                 permutation =
6133                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6134                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6135                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6136                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6137                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6138
6139                 if (r_bloomstate.texture_screen)
6140                 {
6141                         // make sure the buffer is available
6142                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6143
6144                         R_ResetViewRendering2D();
6145                         R_Mesh_SetMainRenderTargets();
6146
6147                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6148                         {
6149                                 // declare variables
6150                                 float speed;
6151                                 static float avgspeed;
6152
6153                                 speed = VectorLength(cl.movement_velocity);
6154
6155                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6156                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6157
6158                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6159                                 speed = bound(0, speed, 1);
6160                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6161
6162                                 // calculate values into a standard alpha
6163                                 cl.motionbluralpha = 1 - exp(-
6164                                                 (
6165                                                  (r_motionblur.value * speed / 80)
6166                                                  +
6167                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6168                                                 )
6169                                                 /
6170                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6171                                            );
6172
6173                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6174                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6175                                 // apply the blur
6176                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6177                                 {
6178                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6179                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6180                                         switch(vid.renderpath)
6181                                         {
6182                                         case RENDERPATH_GL11:
6183                                         case RENDERPATH_GL13:
6184                                         case RENDERPATH_GL20:
6185                                         case RENDERPATH_GLES1:
6186                                         case RENDERPATH_GLES2:
6187                                         case RENDERPATH_SOFT:
6188                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6189                                                 break;
6190                                         case RENDERPATH_D3D9:
6191                                         case RENDERPATH_D3D10:
6192                                         case RENDERPATH_D3D11:
6193                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6194                                                 break;
6195                                         }
6196                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6197                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6198                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6199                                 }
6200                         }
6201
6202                         // copy view into the screen texture
6203                         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);
6204                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6205                 }
6206                 else if (!r_bloomstate.texture_bloom)
6207                 {
6208                         // we may still have to do view tint...
6209                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6210                         {
6211                                 // apply a color tint to the whole view
6212                                 R_ResetViewRendering2D();
6213                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6215                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6216                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6217                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6218                         }
6219                         break; // no screen processing, no bloom, skip it
6220                 }
6221
6222                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6223                 {
6224                         // render simple bloom effect
6225                         // copy the screen and shrink it and darken it for the bloom process
6226                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6227                         // make the bloom texture
6228                         R_Bloom_MakeTexture();
6229                 }
6230
6231 #if _MSC_VER >= 1400
6232 #define sscanf sscanf_s
6233 #endif
6234                 memset(uservecs, 0, sizeof(uservecs));
6235                 if (r_glsl_postprocess_uservec1_enable.integer)
6236                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6237                 if (r_glsl_postprocess_uservec2_enable.integer)
6238                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6239                 if (r_glsl_postprocess_uservec3_enable.integer)
6240                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6241                 if (r_glsl_postprocess_uservec4_enable.integer)
6242                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6243
6244                 R_ResetViewRendering2D();
6245                 GL_Color(1, 1, 1, 1);
6246                 GL_BlendFunc(GL_ONE, GL_ZERO);
6247
6248                 switch(vid.renderpath)
6249                 {
6250                 case RENDERPATH_GL20:
6251                 case RENDERPATH_GLES2:
6252                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6254                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6255                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6256                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6257                         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]);
6258                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259                         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]);
6260                         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]);
6261                         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]);
6262                         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]);
6263                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6264                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265                         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);
6266                         break;
6267                 case RENDERPATH_D3D9:
6268 #ifdef SUPPORTD3D
6269                         // 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...
6270                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6271                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6272                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6273                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6274                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6275                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6276                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6277                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6278                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6279                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6280                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6281                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6282                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6283                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6284 #endif
6285                         break;
6286                 case RENDERPATH_D3D10:
6287                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6288                         break;
6289                 case RENDERPATH_D3D11:
6290                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6291                         break;
6292                 case RENDERPATH_SOFT:
6293                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6294                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6295                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6296                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6297                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6298                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6299                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6300                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6301                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6302                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6303                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6304                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6305                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6306                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6307                         break;
6308                 default:
6309                         break;
6310                 }
6311                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6312                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6313                 break;
6314         case RENDERPATH_GL11:
6315         case RENDERPATH_GL13:
6316         case RENDERPATH_GLES1:
6317                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6318                 {
6319                         // apply a color tint to the whole view
6320                         R_ResetViewRendering2D();
6321                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6322                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6323                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6324                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6326                 }
6327                 break;
6328         }
6329 }
6330
6331 matrix4x4_t r_waterscrollmatrix;
6332
6333 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6334 {
6335         if (r_refdef.fog_density)
6336         {
6337                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6338                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6339                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6340
6341                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6342                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6343                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6344                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6345
6346                 {
6347                         vec3_t fogvec;
6348                         VectorCopy(r_refdef.fogcolor, fogvec);
6349                         //   color.rgb *= ContrastBoost * SceneBrightness;
6350                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6351                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6352                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6353                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6354                 }
6355         }
6356 }
6357
6358 void R_UpdateVariables(void)
6359 {
6360         R_Textures_Frame();
6361
6362         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6363
6364         r_refdef.farclip = r_farclip_base.value;
6365         if (r_refdef.scene.worldmodel)
6366                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6367         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6368
6369         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6370                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6371         r_refdef.polygonfactor = 0;
6372         r_refdef.polygonoffset = 0;
6373         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6374         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6375
6376         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6377         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6378         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6379         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6380         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6381         if (FAKELIGHT_ENABLED)
6382         {
6383                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6384         }
6385         if (r_showsurfaces.integer)
6386         {
6387                 r_refdef.scene.rtworld = false;
6388                 r_refdef.scene.rtworldshadows = false;
6389                 r_refdef.scene.rtdlight = false;
6390                 r_refdef.scene.rtdlightshadows = false;
6391                 r_refdef.lightmapintensity = 0;
6392         }
6393
6394         if (gamemode == GAME_NEHAHRA)
6395         {
6396                 if (gl_fogenable.integer)
6397                 {
6398                         r_refdef.oldgl_fogenable = true;
6399                         r_refdef.fog_density = gl_fogdensity.value;
6400                         r_refdef.fog_red = gl_fogred.value;
6401                         r_refdef.fog_green = gl_foggreen.value;
6402                         r_refdef.fog_blue = gl_fogblue.value;
6403                         r_refdef.fog_alpha = 1;
6404                         r_refdef.fog_start = 0;
6405                         r_refdef.fog_end = gl_skyclip.value;
6406                         r_refdef.fog_height = 1<<30;
6407                         r_refdef.fog_fadedepth = 128;
6408                 }
6409                 else if (r_refdef.oldgl_fogenable)
6410                 {
6411                         r_refdef.oldgl_fogenable = false;
6412                         r_refdef.fog_density = 0;
6413                         r_refdef.fog_red = 0;
6414                         r_refdef.fog_green = 0;
6415                         r_refdef.fog_blue = 0;
6416                         r_refdef.fog_alpha = 0;
6417                         r_refdef.fog_start = 0;
6418                         r_refdef.fog_end = 0;
6419                         r_refdef.fog_height = 1<<30;
6420                         r_refdef.fog_fadedepth = 128;
6421                 }
6422         }
6423
6424         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6425         r_refdef.fog_start = max(0, r_refdef.fog_start);
6426         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6427
6428         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6429
6430         if (r_refdef.fog_density && r_drawfog.integer)
6431         {
6432                 r_refdef.fogenabled = true;
6433                 // this is the point where the fog reaches 0.9986 alpha, which we
6434                 // consider a good enough cutoff point for the texture
6435                 // (0.9986 * 256 == 255.6)
6436                 if (r_fog_exp2.integer)
6437                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6438                 else
6439                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6440                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6441                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6442                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6443                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6444                         R_BuildFogHeightTexture();
6445                 // fog color was already set
6446                 // update the fog texture
6447                 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)
6448                         R_BuildFogTexture();
6449                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6450                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6451         }
6452         else
6453                 r_refdef.fogenabled = false;
6454
6455         switch(vid.renderpath)
6456         {
6457         case RENDERPATH_GL20:
6458         case RENDERPATH_D3D9:
6459         case RENDERPATH_D3D10:
6460         case RENDERPATH_D3D11:
6461         case RENDERPATH_SOFT:
6462         case RENDERPATH_GLES2:
6463                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6464                 {
6465                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6466                         {
6467                                 // build GLSL gamma texture
6468 #define RAMPWIDTH 256
6469                                 unsigned short ramp[RAMPWIDTH * 3];
6470                                 unsigned char rampbgr[RAMPWIDTH][4];
6471                                 int i;
6472
6473                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6474
6475                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6476                                 for(i = 0; i < RAMPWIDTH; ++i)
6477                                 {
6478                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6479                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6480                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6481                                         rampbgr[i][3] = 0;
6482                                 }
6483                                 if (r_texture_gammaramps)
6484                                 {
6485                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6486                                 }
6487                                 else
6488                                 {
6489                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6490                                 }
6491                         }
6492                 }
6493                 else
6494                 {
6495                         // remove GLSL gamma texture
6496                 }
6497                 break;
6498         case RENDERPATH_GL11:
6499         case RENDERPATH_GL13:
6500         case RENDERPATH_GLES1:
6501                 break;
6502         }
6503 }
6504
6505 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6506 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6507 /*
6508 ================
6509 R_SelectScene
6510 ================
6511 */
6512 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6513         if( scenetype != r_currentscenetype ) {
6514                 // store the old scenetype
6515                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6516                 r_currentscenetype = scenetype;
6517                 // move in the new scene
6518                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6519         }
6520 }
6521
6522 /*
6523 ================
6524 R_GetScenePointer
6525 ================
6526 */
6527 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6528 {
6529         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6530         if( scenetype == r_currentscenetype ) {
6531                 return &r_refdef.scene;
6532         } else {
6533                 return &r_scenes_store[ scenetype ];
6534         }
6535 }
6536
6537 /*
6538 ================
6539 R_RenderView
6540 ================
6541 */
6542 int dpsoftrast_test;
6543 void R_RenderView(void)
6544 {
6545         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6546
6547         dpsoftrast_test = r_test.integer;
6548
6549         if (r_timereport_active)
6550                 R_TimeReport("start");
6551         r_textureframe++; // used only by R_GetCurrentTexture
6552         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6553
6554         if(R_CompileShader_CheckStaticParms())
6555                 R_GLSL_Restart_f();
6556
6557         if (!r_drawentities.integer)
6558                 r_refdef.scene.numentities = 0;
6559
6560         R_AnimCache_ClearCache();
6561         R_FrameData_NewFrame();
6562
6563         /* adjust for stereo display */
6564         if(R_Stereo_Active())
6565         {
6566                 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);
6567                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6568         }
6569
6570         if (r_refdef.view.isoverlay)
6571         {
6572                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6573                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6574                 R_TimeReport("depthclear");
6575
6576                 r_refdef.view.showdebug = false;
6577
6578                 r_waterstate.enabled = false;
6579                 r_waterstate.numwaterplanes = 0;
6580
6581                 R_RenderScene();
6582
6583                 r_refdef.view.matrix = originalmatrix;
6584
6585                 CHECKGLERROR
6586                 return;
6587         }
6588
6589         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6590         {
6591                 r_refdef.view.matrix = originalmatrix;
6592                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6593         }
6594
6595         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6596
6597         R_RenderView_UpdateViewVectors();
6598
6599         R_Shadow_UpdateWorldLightSelection();
6600
6601         R_Bloom_StartFrame();
6602         R_Water_StartFrame();
6603
6604         CHECKGLERROR
6605         if (r_timereport_active)
6606                 R_TimeReport("viewsetup");
6607
6608         R_ResetViewRendering3D();
6609
6610         if (r_refdef.view.clear || r_refdef.fogenabled)
6611         {
6612                 R_ClearScreen(r_refdef.fogenabled);
6613                 if (r_timereport_active)
6614                         R_TimeReport("viewclear");
6615         }
6616         r_refdef.view.clear = true;
6617
6618         // this produces a bloom texture to be used in R_BlendView() later
6619         if (r_bloomstate.hdr)
6620         {
6621                 R_HDR_RenderBloomTexture();
6622                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6623                 r_textureframe++; // used only by R_GetCurrentTexture
6624         }
6625
6626         r_refdef.view.showdebug = true;
6627
6628         R_View_Update();
6629         if (r_timereport_active)
6630                 R_TimeReport("visibility");
6631
6632         r_waterstate.numwaterplanes = 0;
6633         if (r_waterstate.enabled)
6634                 R_RenderWaterPlanes();
6635
6636         R_RenderScene();
6637         r_waterstate.numwaterplanes = 0;
6638
6639         R_BlendView();
6640         if (r_timereport_active)
6641                 R_TimeReport("blendview");
6642
6643         GL_Scissor(0, 0, vid.width, vid.height);
6644         GL_ScissorTest(false);
6645
6646         r_refdef.view.matrix = originalmatrix;
6647
6648         CHECKGLERROR
6649 }
6650
6651 void R_RenderWaterPlanes(void)
6652 {
6653         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6654         {
6655                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6656                 if (r_timereport_active)
6657                         R_TimeReport("waterworld");
6658         }
6659
6660         // don't let sound skip if going slow
6661         if (r_refdef.scene.extraupdate)
6662                 S_ExtraUpdate ();
6663
6664         R_DrawModelsAddWaterPlanes();
6665         if (r_timereport_active)
6666                 R_TimeReport("watermodels");
6667
6668         if (r_waterstate.numwaterplanes)
6669         {
6670                 R_Water_ProcessPlanes();
6671                 if (r_timereport_active)
6672                         R_TimeReport("waterscenes");
6673         }
6674 }
6675
6676 extern void R_DrawLightningBeams (void);
6677 extern void VM_CL_AddPolygonsToMeshQueue (void);
6678 extern void R_DrawPortals (void);
6679 extern cvar_t cl_locs_show;
6680 static void R_DrawLocs(void);
6681 static void R_DrawEntityBBoxes(void);
6682 static void R_DrawModelDecals(void);
6683 extern void R_DrawModelShadows(void);
6684 extern void R_DrawModelShadowMaps(void);
6685 extern cvar_t cl_decals_newsystem;
6686 extern qboolean r_shadow_usingdeferredprepass;
6687 void R_RenderScene(void)
6688 {
6689         qboolean shadowmapping = false;
6690
6691         if (r_timereport_active)
6692                 R_TimeReport("beginscene");
6693
6694         r_refdef.stats.renders++;
6695
6696         R_UpdateFogColor();
6697
6698         // don't let sound skip if going slow
6699         if (r_refdef.scene.extraupdate)
6700                 S_ExtraUpdate ();
6701
6702         R_MeshQueue_BeginScene();
6703
6704         R_SkyStartFrame();
6705
6706         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);
6707
6708         if (r_timereport_active)
6709                 R_TimeReport("skystartframe");
6710
6711         if (cl.csqc_vidvars.drawworld)
6712         {
6713                 // don't let sound skip if going slow
6714                 if (r_refdef.scene.extraupdate)
6715                         S_ExtraUpdate ();
6716
6717                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6718                 {
6719                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6720                         if (r_timereport_active)
6721                                 R_TimeReport("worldsky");
6722                 }
6723
6724                 if (R_DrawBrushModelsSky() && r_timereport_active)
6725                         R_TimeReport("bmodelsky");
6726
6727                 if (skyrendermasked && skyrenderlater)
6728                 {
6729                         // we have to force off the water clipping plane while rendering sky
6730                         R_SetupView(false);
6731                         R_Sky();
6732                         R_SetupView(true);
6733                         if (r_timereport_active)
6734                                 R_TimeReport("sky");
6735                 }
6736         }
6737
6738         R_AnimCache_CacheVisibleEntities();
6739         if (r_timereport_active)
6740                 R_TimeReport("animation");
6741
6742         R_Shadow_PrepareLights();
6743         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6744                 R_Shadow_PrepareModelShadows();
6745         if (r_timereport_active)
6746                 R_TimeReport("preparelights");
6747
6748         if (R_Shadow_ShadowMappingEnabled())
6749                 shadowmapping = true;
6750
6751         if (r_shadow_usingdeferredprepass)
6752                 R_Shadow_DrawPrepass();
6753
6754         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6755         {
6756                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6757                 if (r_timereport_active)
6758                         R_TimeReport("worlddepth");
6759         }
6760         if (r_depthfirst.integer >= 2)
6761         {
6762                 R_DrawModelsDepth();
6763                 if (r_timereport_active)
6764                         R_TimeReport("modeldepth");
6765         }
6766
6767         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6768         {
6769                 R_DrawModelShadowMaps();
6770                 R_ResetViewRendering3D();
6771                 // don't let sound skip if going slow
6772                 if (r_refdef.scene.extraupdate)
6773                         S_ExtraUpdate ();
6774         }
6775
6776         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6777         {
6778                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6779                 if (r_timereport_active)
6780                         R_TimeReport("world");
6781         }
6782
6783         // don't let sound skip if going slow
6784         if (r_refdef.scene.extraupdate)
6785                 S_ExtraUpdate ();
6786
6787         R_DrawModels();
6788         if (r_timereport_active)
6789                 R_TimeReport("models");
6790
6791         // don't let sound skip if going slow
6792         if (r_refdef.scene.extraupdate)
6793                 S_ExtraUpdate ();
6794
6795         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6796         {
6797                 R_DrawModelShadows();
6798                 R_ResetViewRendering3D();
6799                 // don't let sound skip if going slow
6800                 if (r_refdef.scene.extraupdate)
6801                         S_ExtraUpdate ();
6802         }
6803
6804         if (!r_shadow_usingdeferredprepass)
6805         {
6806                 R_Shadow_DrawLights();
6807                 if (r_timereport_active)
6808                         R_TimeReport("rtlights");
6809         }
6810
6811         // don't let sound skip if going slow
6812         if (r_refdef.scene.extraupdate)
6813                 S_ExtraUpdate ();
6814
6815         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6816         {
6817                 R_DrawModelShadows();
6818                 R_ResetViewRendering3D();
6819                 // don't let sound skip if going slow
6820                 if (r_refdef.scene.extraupdate)
6821                         S_ExtraUpdate ();
6822         }
6823
6824         if (cl.csqc_vidvars.drawworld)
6825         {
6826                 if (cl_decals_newsystem.integer)
6827                 {
6828                         R_DrawModelDecals();
6829                         if (r_timereport_active)
6830                                 R_TimeReport("modeldecals");
6831                 }
6832                 else
6833                 {
6834                         R_DrawDecals();
6835                         if (r_timereport_active)
6836                                 R_TimeReport("decals");
6837                 }
6838
6839                 R_DrawParticles();
6840                 if (r_timereport_active)
6841                         R_TimeReport("particles");
6842
6843                 R_DrawExplosions();
6844                 if (r_timereport_active)
6845                         R_TimeReport("explosions");
6846
6847                 R_DrawLightningBeams();
6848                 if (r_timereport_active)
6849                         R_TimeReport("lightning");
6850         }
6851
6852         VM_CL_AddPolygonsToMeshQueue();
6853
6854         if (r_refdef.view.showdebug)
6855         {
6856                 if (cl_locs_show.integer)
6857                 {
6858                         R_DrawLocs();
6859                         if (r_timereport_active)
6860                                 R_TimeReport("showlocs");
6861                 }
6862
6863                 if (r_drawportals.integer)
6864                 {
6865                         R_DrawPortals();
6866                         if (r_timereport_active)
6867                                 R_TimeReport("portals");
6868                 }
6869
6870                 if (r_showbboxes.value > 0)
6871                 {
6872                         R_DrawEntityBBoxes();
6873                         if (r_timereport_active)
6874                                 R_TimeReport("bboxes");
6875                 }
6876         }
6877
6878         if (r_transparent.integer)
6879         {
6880                 R_MeshQueue_RenderTransparent();
6881                 if (r_timereport_active)
6882                         R_TimeReport("drawtrans");
6883         }
6884
6885         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))
6886         {
6887                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6888                 if (r_timereport_active)
6889                         R_TimeReport("worlddebug");
6890                 R_DrawModelsDebug();
6891                 if (r_timereport_active)
6892                         R_TimeReport("modeldebug");
6893         }
6894
6895         if (cl.csqc_vidvars.drawworld)
6896         {
6897                 R_Shadow_DrawCoronas();
6898                 if (r_timereport_active)
6899                         R_TimeReport("coronas");
6900         }
6901
6902 #if 0
6903         {
6904                 GL_DepthTest(false);
6905                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6906                 GL_Color(1, 1, 1, 1);
6907                 qglBegin(GL_POLYGON);
6908                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6909                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6910                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6911                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6912                 qglEnd();
6913                 qglBegin(GL_POLYGON);
6914                 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]);
6915                 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]);
6916                 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]);
6917                 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]);
6918                 qglEnd();
6919                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6920         }
6921 #endif
6922
6923         // don't let sound skip if going slow
6924         if (r_refdef.scene.extraupdate)
6925                 S_ExtraUpdate ();
6926
6927         R_ResetViewRendering2D();
6928 }
6929
6930 static const unsigned short bboxelements[36] =
6931 {
6932         5, 1, 3, 5, 3, 7,
6933         6, 2, 0, 6, 0, 4,
6934         7, 3, 2, 7, 2, 6,
6935         4, 0, 1, 4, 1, 5,
6936         4, 5, 7, 4, 7, 6,
6937         1, 0, 2, 1, 2, 3,
6938 };
6939
6940 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6941 {
6942         int i;
6943         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6944
6945         RSurf_ActiveWorldEntity();
6946
6947         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948         GL_DepthMask(false);
6949         GL_DepthRange(0, 1);
6950         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6951 //      R_Mesh_ResetTextureState();
6952
6953         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6954         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6955         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6956         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6957         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6958         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6959         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6960         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6961         R_FillColors(color4f, 8, cr, cg, cb, ca);
6962         if (r_refdef.fogenabled)
6963         {
6964                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6965                 {
6966                         f1 = RSurf_FogVertex(v);
6967                         f2 = 1 - f1;
6968                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6969                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6970                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6971                 }
6972         }
6973         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6974         R_Mesh_ResetTextureState();
6975         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6976         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6977 }
6978
6979 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6980 {
6981         int i;
6982         float color[4];
6983         prvm_edict_t *edict;
6984         prvm_prog_t *prog_save = prog;
6985
6986         // this function draws bounding boxes of server entities
6987         if (!sv.active)
6988                 return;
6989
6990         GL_CullFace(GL_NONE);
6991         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6992
6993         prog = 0;
6994         SV_VM_Begin();
6995         for (i = 0;i < numsurfaces;i++)
6996         {
6997                 edict = PRVM_EDICT_NUM(surfacelist[i]);
6998                 switch ((int)edict->fields.server->solid)
6999                 {
7000                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7001                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7002                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7003                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7004                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7005                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7006                 }
7007                 color[3] *= r_showbboxes.value;
7008                 color[3] = bound(0, color[3], 1);
7009                 GL_DepthTest(!r_showdisabledepthtest.integer);
7010                 GL_CullFace(r_refdef.view.cullface_front);
7011                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7012         }
7013         SV_VM_End();
7014         prog = prog_save;
7015 }
7016
7017 static void R_DrawEntityBBoxes(void)
7018 {
7019         int i;
7020         prvm_edict_t *edict;
7021         vec3_t center;
7022         prvm_prog_t *prog_save = prog;
7023
7024         // this function draws bounding boxes of server entities
7025         if (!sv.active)
7026                 return;
7027
7028         prog = 0;
7029         SV_VM_Begin();
7030         for (i = 0;i < prog->num_edicts;i++)
7031         {
7032                 edict = PRVM_EDICT_NUM(i);
7033                 if (edict->priv.server->free)
7034                         continue;
7035                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7036                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7037                         continue;
7038                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7039                         continue;
7040                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7041                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7042         }
7043         SV_VM_End();
7044         prog = prog_save;
7045 }
7046
7047 static const int nomodelelement3i[24] =
7048 {
7049         5, 2, 0,
7050         5, 1, 2,
7051         5, 0, 3,
7052         5, 3, 1,
7053         0, 2, 4,
7054         2, 1, 4,
7055         3, 0, 4,
7056         1, 3, 4
7057 };
7058
7059 static const unsigned short nomodelelement3s[24] =
7060 {
7061         5, 2, 0,
7062         5, 1, 2,
7063         5, 0, 3,
7064         5, 3, 1,
7065         0, 2, 4,
7066         2, 1, 4,
7067         3, 0, 4,
7068         1, 3, 4
7069 };
7070
7071 static const float nomodelvertex3f[6*3] =
7072 {
7073         -16,   0,   0,
7074          16,   0,   0,
7075           0, -16,   0,
7076           0,  16,   0,
7077           0,   0, -16,
7078           0,   0,  16
7079 };
7080
7081 static const float nomodelcolor4f[6*4] =
7082 {
7083         0.0f, 0.0f, 0.5f, 1.0f,
7084         0.0f, 0.0f, 0.5f, 1.0f,
7085         0.0f, 0.5f, 0.0f, 1.0f,
7086         0.0f, 0.5f, 0.0f, 1.0f,
7087         0.5f, 0.0f, 0.0f, 1.0f,
7088         0.5f, 0.0f, 0.0f, 1.0f
7089 };
7090
7091 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7092 {
7093         int i;
7094         float f1, f2, *c;
7095         float color4f[6*4];
7096
7097         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);
7098
7099         // this is only called once per entity so numsurfaces is always 1, and
7100         // surfacelist is always {0}, so this code does not handle batches
7101
7102         if (rsurface.ent_flags & RENDER_ADDITIVE)
7103         {
7104                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7105                 GL_DepthMask(false);
7106         }
7107         else if (rsurface.colormod[3] < 1)
7108         {
7109                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7110                 GL_DepthMask(false);
7111         }
7112         else
7113         {
7114                 GL_BlendFunc(GL_ONE, GL_ZERO);
7115                 GL_DepthMask(true);
7116         }
7117         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7118         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7119         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7120         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7121         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7122         for (i = 0, c = color4f;i < 6;i++, c += 4)
7123         {
7124                 c[0] *= rsurface.colormod[0];
7125                 c[1] *= rsurface.colormod[1];
7126                 c[2] *= rsurface.colormod[2];
7127                 c[3] *= rsurface.colormod[3];
7128         }
7129         if (r_refdef.fogenabled)
7130         {
7131                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7132                 {
7133                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7134                         f2 = 1 - f1;
7135                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7136                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7137                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7138                 }
7139         }
7140 //      R_Mesh_ResetTextureState();
7141         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7142         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7143         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7144 }
7145
7146 void R_DrawNoModel(entity_render_t *ent)
7147 {
7148         vec3_t org;
7149         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7150         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7151                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7152         else
7153                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7154 }
7155
7156 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7157 {
7158         vec3_t right1, right2, diff, normal;
7159
7160         VectorSubtract (org2, org1, normal);
7161
7162         // calculate 'right' vector for start
7163         VectorSubtract (r_refdef.view.origin, org1, diff);
7164         CrossProduct (normal, diff, right1);
7165         VectorNormalize (right1);
7166
7167         // calculate 'right' vector for end
7168         VectorSubtract (r_refdef.view.origin, org2, diff);
7169         CrossProduct (normal, diff, right2);
7170         VectorNormalize (right2);
7171
7172         vert[ 0] = org1[0] + width * right1[0];
7173         vert[ 1] = org1[1] + width * right1[1];
7174         vert[ 2] = org1[2] + width * right1[2];
7175         vert[ 3] = org1[0] - width * right1[0];
7176         vert[ 4] = org1[1] - width * right1[1];
7177         vert[ 5] = org1[2] - width * right1[2];
7178         vert[ 6] = org2[0] - width * right2[0];
7179         vert[ 7] = org2[1] - width * right2[1];
7180         vert[ 8] = org2[2] - width * right2[2];
7181         vert[ 9] = org2[0] + width * right2[0];
7182         vert[10] = org2[1] + width * right2[1];
7183         vert[11] = org2[2] + width * right2[2];
7184 }
7185
7186 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)
7187 {
7188         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7189         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7190         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7191         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7192         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7193         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7194         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7195         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7196         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7197         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7198         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7199         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7200 }
7201
7202 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7203 {
7204         int i;
7205         float *vertex3f;
7206         float v[3];
7207         VectorSet(v, x, y, z);
7208         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7209                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7210                         break;
7211         if (i == mesh->numvertices)
7212         {
7213                 if (mesh->numvertices < mesh->maxvertices)
7214                 {
7215                         VectorCopy(v, vertex3f);
7216                         mesh->numvertices++;
7217                 }
7218                 return mesh->numvertices;
7219         }
7220         else
7221                 return i;
7222 }
7223
7224 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7225 {
7226         int i;
7227         int *e, element[3];
7228         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7229         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7230         e = mesh->element3i + mesh->numtriangles * 3;
7231         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7232         {
7233                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7234                 if (mesh->numtriangles < mesh->maxtriangles)
7235                 {
7236                         *e++ = element[0];
7237                         *e++ = element[1];
7238                         *e++ = element[2];
7239                         mesh->numtriangles++;
7240                 }
7241                 element[1] = element[2];
7242         }
7243 }
7244
7245 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7246 {
7247         int i;
7248         int *e, element[3];
7249         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7250         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7251         e = mesh->element3i + mesh->numtriangles * 3;
7252         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7253         {
7254                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7255                 if (mesh->numtriangles < mesh->maxtriangles)
7256                 {
7257                         *e++ = element[0];
7258                         *e++ = element[1];
7259                         *e++ = element[2];
7260                         mesh->numtriangles++;
7261                 }
7262                 element[1] = element[2];
7263         }
7264 }
7265
7266 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7267 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7268 {
7269         int planenum, planenum2;
7270         int w;
7271         int tempnumpoints;
7272         mplane_t *plane, *plane2;
7273         double maxdist;
7274         double temppoints[2][256*3];
7275         // figure out how large a bounding box we need to properly compute this brush
7276         maxdist = 0;
7277         for (w = 0;w < numplanes;w++)
7278                 maxdist = max(maxdist, fabs(planes[w].dist));
7279         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7280         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7281         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7282         {
7283                 w = 0;
7284                 tempnumpoints = 4;
7285                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7286                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7287                 {
7288                         if (planenum2 == planenum)
7289                                 continue;
7290                         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);
7291                         w = !w;
7292                 }
7293                 if (tempnumpoints < 3)
7294                         continue;
7295                 // generate elements forming a triangle fan for this polygon
7296                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7297         }
7298 }
7299
7300 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)
7301 {
7302         texturelayer_t *layer;
7303         layer = t->currentlayers + t->currentnumlayers++;
7304         layer->type = type;
7305         layer->depthmask = depthmask;
7306         layer->blendfunc1 = blendfunc1;
7307         layer->blendfunc2 = blendfunc2;
7308         layer->texture = texture;
7309         layer->texmatrix = *matrix;
7310         layer->color[0] = r;
7311         layer->color[1] = g;
7312         layer->color[2] = b;
7313         layer->color[3] = a;
7314 }
7315
7316 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7317 {
7318         if(parms[0] == 0 && parms[1] == 0)
7319                 return false;
7320         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7322                         return false;
7323         return true;
7324 }
7325
7326 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7327 {
7328         double index, f;
7329         index = parms[2] + r_refdef.scene.time * parms[3];
7330         index -= floor(index);
7331         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7332         {
7333         default:
7334         case Q3WAVEFUNC_NONE:
7335         case Q3WAVEFUNC_NOISE:
7336         case Q3WAVEFUNC_COUNT:
7337                 f = 0;
7338                 break;
7339         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7340         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7341         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7342         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7343         case Q3WAVEFUNC_TRIANGLE:
7344                 index *= 4;
7345                 f = index - floor(index);
7346                 if (index < 1)
7347                         f = f;
7348                 else if (index < 2)
7349                         f = 1 - f;
7350                 else if (index < 3)
7351                         f = -f;
7352                 else
7353                         f = -(1 - f);
7354                 break;
7355         }
7356         f = parms[0] + parms[1] * f;
7357         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7358                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7359         return (float) f;
7360 }
7361
7362 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7363 {
7364         int w, h, idx;
7365         float f;
7366         float tcmat[12];
7367         matrix4x4_t matrix, temp;
7368         switch(tcmod->tcmod)
7369         {
7370                 case Q3TCMOD_COUNT:
7371                 case Q3TCMOD_NONE:
7372                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7373                                 matrix = r_waterscrollmatrix;
7374                         else
7375                                 matrix = identitymatrix;
7376                         break;
7377                 case Q3TCMOD_ENTITYTRANSLATE:
7378                         // this is used in Q3 to allow the gamecode to control texcoord
7379                         // scrolling on the entity, which is not supported in darkplaces yet.
7380                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7381                         break;
7382                 case Q3TCMOD_ROTATE:
7383                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7384                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7385                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7386                         break;
7387                 case Q3TCMOD_SCALE:
7388                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7389                         break;
7390                 case Q3TCMOD_SCROLL:
7391                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7392                         break;
7393                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7394                         w = (int) tcmod->parms[0];
7395                         h = (int) tcmod->parms[1];
7396                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7397                         f = f - floor(f);
7398                         idx = (int) floor(f * w * h);
7399                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7400                         break;
7401                 case Q3TCMOD_STRETCH:
7402                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7403                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7404                         break;
7405                 case Q3TCMOD_TRANSFORM:
7406                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7407                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7408                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7409                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7410                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7411                         break;
7412                 case Q3TCMOD_TURBULENT:
7413                         // this is handled in the RSurf_PrepareVertices function
7414                         matrix = identitymatrix;
7415                         break;
7416         }
7417         temp = *texmatrix;
7418         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7419 }
7420
7421 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7422 {
7423         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7424         char name[MAX_QPATH];
7425         skinframe_t *skinframe;
7426         unsigned char pixels[296*194];
7427         strlcpy(cache->name, skinname, sizeof(cache->name));
7428         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7429         if (developer_loading.integer)
7430                 Con_Printf("loading %s\n", name);
7431         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7432         if (!skinframe || !skinframe->base)
7433         {
7434                 unsigned char *f;
7435                 fs_offset_t filesize;
7436                 skinframe = NULL;
7437                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7438                 if (f)
7439                 {
7440                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7441                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7442                         Mem_Free(f);
7443                 }
7444         }
7445         cache->skinframe = skinframe;
7446 }
7447
7448 texture_t *R_GetCurrentTexture(texture_t *t)
7449 {
7450         int i;
7451         const entity_render_t *ent = rsurface.entity;
7452         dp_model_t *model = ent->model;
7453         q3shaderinfo_layer_tcmod_t *tcmod;
7454
7455         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7456                 return t->currentframe;
7457         t->update_lastrenderframe = r_textureframe;
7458         t->update_lastrenderentity = (void *)ent;
7459
7460         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7461                 t->camera_entity = ent->entitynumber;
7462         else
7463                 t->camera_entity = 0;
7464
7465         // switch to an alternate material if this is a q1bsp animated material
7466         {
7467                 texture_t *texture = t;
7468                 int s = rsurface.ent_skinnum;
7469                 if ((unsigned int)s >= (unsigned int)model->numskins)
7470                         s = 0;
7471                 if (model->skinscenes)
7472                 {
7473                         if (model->skinscenes[s].framecount > 1)
7474                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7475                         else
7476                                 s = model->skinscenes[s].firstframe;
7477                 }
7478                 if (s > 0)
7479                         t = t + s * model->num_surfaces;
7480                 if (t->animated)
7481                 {
7482                         // use an alternate animation if the entity's frame is not 0,
7483                         // and only if the texture has an alternate animation
7484                         if (rsurface.ent_alttextures && t->anim_total[1])
7485                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7486                         else
7487                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7488                 }
7489                 texture->currentframe = t;
7490         }
7491
7492         // update currentskinframe to be a qw skin or animation frame
7493         if (rsurface.ent_qwskin >= 0)
7494         {
7495                 i = rsurface.ent_qwskin;
7496                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7497                 {
7498                         r_qwskincache_size = cl.maxclients;
7499                         if (r_qwskincache)
7500                                 Mem_Free(r_qwskincache);
7501                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7502                 }
7503                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7504                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7505                 t->currentskinframe = r_qwskincache[i].skinframe;
7506                 if (t->currentskinframe == NULL)
7507                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7508         }
7509         else if (t->numskinframes >= 2)
7510                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7511         if (t->backgroundnumskinframes >= 2)
7512                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7513
7514         t->currentmaterialflags = t->basematerialflags;
7515         t->currentalpha = rsurface.colormod[3];
7516         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7517                 t->currentalpha *= r_wateralpha.value;
7518         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7519                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7520         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7521                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7522         if (!(rsurface.ent_flags & RENDER_LIGHT))
7523                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7524         else if (FAKELIGHT_ENABLED)
7525         {
7526                 // no modellight if using fakelight for the map
7527         }
7528         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7529         {
7530                 // pick a model lighting mode
7531                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7532                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7533                 else
7534                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7535         }
7536         if (rsurface.ent_flags & RENDER_ADDITIVE)
7537                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538         else if (t->currentalpha < 1)
7539                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7540         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7541                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7542         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7543                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7544         if (t->backgroundnumskinframes)
7545                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7546         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7547         {
7548                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7549                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7550         }
7551         else
7552                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7553         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7554                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7555
7556         // there is no tcmod
7557         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7558         {
7559                 t->currenttexmatrix = r_waterscrollmatrix;
7560                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7561         }
7562         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7563         {
7564                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7565                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7566         }
7567
7568         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7570         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7571                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7572
7573         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7574         if (t->currentskinframe->qpixels)
7575                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7576         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7577         if (!t->basetexture)
7578                 t->basetexture = r_texture_notexture;
7579         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7580         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7581         t->nmaptexture = t->currentskinframe->nmap;
7582         if (!t->nmaptexture)
7583                 t->nmaptexture = r_texture_blanknormalmap;
7584         t->glosstexture = r_texture_black;
7585         t->glowtexture = t->currentskinframe->glow;
7586         t->fogtexture = t->currentskinframe->fog;
7587         t->reflectmasktexture = t->currentskinframe->reflect;
7588         if (t->backgroundnumskinframes)
7589         {
7590                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7591                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7592                 t->backgroundglosstexture = r_texture_black;
7593                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7594                 if (!t->backgroundnmaptexture)
7595                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7596         }
7597         else
7598         {
7599                 t->backgroundbasetexture = r_texture_white;
7600                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7601                 t->backgroundglosstexture = r_texture_black;
7602                 t->backgroundglowtexture = NULL;
7603         }
7604         t->specularpower = r_shadow_glossexponent.value;
7605         // TODO: store reference values for these in the texture?
7606         t->specularscale = 0;
7607         if (r_shadow_gloss.integer > 0)
7608         {
7609                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7610                 {
7611                         if (r_shadow_glossintensity.value > 0)
7612                         {
7613                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7614                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7615                                 t->specularscale = r_shadow_glossintensity.value;
7616                         }
7617                 }
7618                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7619                 {
7620                         t->glosstexture = r_texture_white;
7621                         t->backgroundglosstexture = r_texture_white;
7622                         t->specularscale = r_shadow_gloss2intensity.value;
7623                         t->specularpower = r_shadow_gloss2exponent.value;
7624                 }
7625         }
7626         t->specularscale *= t->specularscalemod;
7627         t->specularpower *= t->specularpowermod;
7628
7629         // lightmaps mode looks bad with dlights using actual texturing, so turn
7630         // off the colormap and glossmap, but leave the normalmap on as it still
7631         // accurately represents the shading involved
7632         if (gl_lightmaps.integer)
7633         {
7634                 t->basetexture = r_texture_grey128;
7635                 t->pantstexture = r_texture_black;
7636                 t->shirttexture = r_texture_black;
7637                 t->nmaptexture = r_texture_blanknormalmap;
7638                 t->glosstexture = r_texture_black;
7639                 t->glowtexture = NULL;
7640                 t->fogtexture = NULL;
7641                 t->reflectmasktexture = NULL;
7642                 t->backgroundbasetexture = NULL;
7643                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7644                 t->backgroundglosstexture = r_texture_black;
7645                 t->backgroundglowtexture = NULL;
7646                 t->specularscale = 0;
7647                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7648         }
7649
7650         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7651         VectorClear(t->dlightcolor);
7652         t->currentnumlayers = 0;
7653         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7654         {
7655                 int blendfunc1, blendfunc2;
7656                 qboolean depthmask;
7657                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7658                 {
7659                         blendfunc1 = GL_SRC_ALPHA;
7660                         blendfunc2 = GL_ONE;
7661                 }
7662                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7663                 {
7664                         blendfunc1 = GL_SRC_ALPHA;
7665                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7666                 }
7667                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7668                 {
7669                         blendfunc1 = t->customblendfunc[0];
7670                         blendfunc2 = t->customblendfunc[1];
7671                 }
7672                 else
7673                 {
7674                         blendfunc1 = GL_ONE;
7675                         blendfunc2 = GL_ZERO;
7676                 }
7677                 // don't colormod evilblend textures
7678                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7679                         VectorSet(t->lightmapcolor, 1, 1, 1);
7680                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7681                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7682                 {
7683                         // fullbright is not affected by r_refdef.lightmapintensity
7684                         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]);
7685                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7686                                 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]);
7687                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7688                                 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]);
7689                 }
7690                 else
7691                 {
7692                         vec3_t ambientcolor;
7693                         float colorscale;
7694                         // set the color tint used for lights affecting this surface
7695                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7696                         colorscale = 2;
7697                         // q3bsp has no lightmap updates, so the lightstylevalue that
7698                         // would normally be baked into the lightmap must be
7699                         // applied to the color
7700                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7701                         if (model->type == mod_brushq3)
7702                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7703                         colorscale *= r_refdef.lightmapintensity;
7704                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7705                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7706                         // basic lit geometry
7707                         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]);
7708                         // add pants/shirt if needed
7709                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7710                                 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]);
7711                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7712                                 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]);
7713                         // now add ambient passes if needed
7714                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7715                         {
7716                                 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]);
7717                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7718                                         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]);
7719                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7720                                         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]);
7721                         }
7722                 }
7723                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7724                         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]);
7725                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7726                 {
7727                         // if this is opaque use alpha blend which will darken the earlier
7728                         // passes cheaply.
7729                         //
7730                         // if this is an alpha blended material, all the earlier passes
7731                         // were darkened by fog already, so we only need to add the fog
7732                         // color ontop through the fog mask texture
7733                         //
7734                         // if this is an additive blended material, all the earlier passes
7735                         // were darkened by fog already, and we should not add fog color
7736                         // (because the background was not darkened, there is no fog color
7737                         // that was lost behind it).
7738                         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]);
7739                 }
7740         }
7741
7742         return t->currentframe;
7743 }
7744
7745 rsurfacestate_t rsurface;
7746
7747 void RSurf_ActiveWorldEntity(void)
7748 {
7749         dp_model_t *model = r_refdef.scene.worldmodel;
7750         //if (rsurface.entity == r_refdef.scene.worldentity)
7751         //      return;
7752         rsurface.entity = r_refdef.scene.worldentity;
7753         rsurface.skeleton = NULL;
7754         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7755         rsurface.ent_skinnum = 0;
7756         rsurface.ent_qwskin = -1;
7757         rsurface.ent_shadertime = 0;
7758         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7759         rsurface.matrix = identitymatrix;
7760         rsurface.inversematrix = identitymatrix;
7761         rsurface.matrixscale = 1;
7762         rsurface.inversematrixscale = 1;
7763         R_EntityMatrix(&identitymatrix);
7764         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7765         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7766         rsurface.fograngerecip = r_refdef.fograngerecip;
7767         rsurface.fogheightfade = r_refdef.fogheightfade;
7768         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7769         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7770         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7771         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7772         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7773         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7774         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7775         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7776         rsurface.colormod[3] = 1;
7777         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);
7778         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7779         rsurface.frameblend[0].lerp = 1;
7780         rsurface.ent_alttextures = false;
7781         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7782         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7783         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7784         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7785         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7786         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7787         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7789         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7790         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7792         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7793         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7795         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7796         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7798         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7799         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7801         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7802         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7804         rsurface.modelelement3i = model->surfmesh.data_element3i;
7805         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7806         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7807         rsurface.modelelement3s = model->surfmesh.data_element3s;
7808         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7809         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7810         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7811         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7812         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7813         rsurface.modelsurfaces = model->data_surfaces;
7814         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7815         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7816         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7817         rsurface.modelgeneratedvertex = false;
7818         rsurface.batchgeneratedvertex = false;
7819         rsurface.batchfirstvertex = 0;
7820         rsurface.batchnumvertices = 0;
7821         rsurface.batchfirsttriangle = 0;
7822         rsurface.batchnumtriangles = 0;
7823         rsurface.batchvertex3f  = NULL;
7824         rsurface.batchvertex3f_vertexbuffer = NULL;
7825         rsurface.batchvertex3f_bufferoffset = 0;
7826         rsurface.batchsvector3f = NULL;
7827         rsurface.batchsvector3f_vertexbuffer = NULL;
7828         rsurface.batchsvector3f_bufferoffset = 0;
7829         rsurface.batchtvector3f = NULL;
7830         rsurface.batchtvector3f_vertexbuffer = NULL;
7831         rsurface.batchtvector3f_bufferoffset = 0;
7832         rsurface.batchnormal3f  = NULL;
7833         rsurface.batchnormal3f_vertexbuffer = NULL;
7834         rsurface.batchnormal3f_bufferoffset = 0;
7835         rsurface.batchlightmapcolor4f = NULL;
7836         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7837         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7838         rsurface.batchtexcoordtexture2f = NULL;
7839         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7840         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7841         rsurface.batchtexcoordlightmap2f = NULL;
7842         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7843         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7844         rsurface.batchvertexmesh = NULL;
7845         rsurface.batchvertexmeshbuffer = NULL;
7846         rsurface.batchvertex3fbuffer = NULL;
7847         rsurface.batchelement3i = NULL;
7848         rsurface.batchelement3i_indexbuffer = NULL;
7849         rsurface.batchelement3i_bufferoffset = 0;
7850         rsurface.batchelement3s = NULL;
7851         rsurface.batchelement3s_indexbuffer = NULL;
7852         rsurface.batchelement3s_bufferoffset = 0;
7853         rsurface.passcolor4f = NULL;
7854         rsurface.passcolor4f_vertexbuffer = NULL;
7855         rsurface.passcolor4f_bufferoffset = 0;
7856 }
7857
7858 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7859 {
7860         dp_model_t *model = ent->model;
7861         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7862         //      return;
7863         rsurface.entity = (entity_render_t *)ent;
7864         rsurface.skeleton = ent->skeleton;
7865         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7866         rsurface.ent_skinnum = ent->skinnum;
7867         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;
7868         rsurface.ent_shadertime = ent->shadertime;
7869         rsurface.ent_flags = ent->flags;
7870         rsurface.matrix = ent->matrix;
7871         rsurface.inversematrix = ent->inversematrix;
7872         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874         R_EntityMatrix(&rsurface.matrix);
7875         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7882         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7883         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7884         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7885         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7886         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7887         rsurface.colormod[3] = ent->alpha;
7888         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7889         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7890         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7891         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7893         if (ent->model->brush.submodel && !prepass)
7894         {
7895                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7896                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7897         }
7898         if (model->surfmesh.isanimated && model->AnimateVertices)
7899         {
7900                 if (ent->animcache_vertex3f)
7901                 {
7902                         rsurface.modelvertex3f = ent->animcache_vertex3f;
7903                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7904                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7905                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7906                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7907                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7908                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7909                 }
7910                 else if (wanttangents)
7911                 {
7912                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7915                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7916                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7917                         rsurface.modelvertexmesh = NULL;
7918                         rsurface.modelvertexmeshbuffer = NULL;
7919                         rsurface.modelvertex3fbuffer = NULL;
7920                 }
7921                 else if (wantnormals)
7922                 {
7923                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924                         rsurface.modelsvector3f = NULL;
7925                         rsurface.modeltvector3f = NULL;
7926                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7928                         rsurface.modelvertexmesh = NULL;
7929                         rsurface.modelvertexmeshbuffer = NULL;
7930                         rsurface.modelvertex3fbuffer = NULL;
7931                 }
7932                 else
7933                 {
7934                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935                         rsurface.modelsvector3f = NULL;
7936                         rsurface.modeltvector3f = NULL;
7937                         rsurface.modelnormal3f = NULL;
7938                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7939                         rsurface.modelvertexmesh = NULL;
7940                         rsurface.modelvertexmeshbuffer = NULL;
7941                         rsurface.modelvertex3fbuffer = NULL;
7942                 }
7943                 rsurface.modelvertex3f_vertexbuffer = 0;
7944                 rsurface.modelvertex3f_bufferoffset = 0;
7945                 rsurface.modelsvector3f_vertexbuffer = 0;
7946                 rsurface.modelsvector3f_bufferoffset = 0;
7947                 rsurface.modeltvector3f_vertexbuffer = 0;
7948                 rsurface.modeltvector3f_bufferoffset = 0;
7949                 rsurface.modelnormal3f_vertexbuffer = 0;
7950                 rsurface.modelnormal3f_bufferoffset = 0;
7951                 rsurface.modelgeneratedvertex = true;
7952         }
7953         else
7954         {
7955                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7956                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7958                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7959                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7961                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7962                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7964                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7965                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7967                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7968                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7969                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7970                 rsurface.modelgeneratedvertex = false;
7971         }
7972         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7973         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7975         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7976         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7978         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7979         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7981         rsurface.modelelement3i = model->surfmesh.data_element3i;
7982         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7983         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7984         rsurface.modelelement3s = model->surfmesh.data_element3s;
7985         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7986         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7987         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7988         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7989         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7990         rsurface.modelsurfaces = model->data_surfaces;
7991         rsurface.batchgeneratedvertex = false;
7992         rsurface.batchfirstvertex = 0;
7993         rsurface.batchnumvertices = 0;
7994         rsurface.batchfirsttriangle = 0;
7995         rsurface.batchnumtriangles = 0;
7996         rsurface.batchvertex3f  = NULL;
7997         rsurface.batchvertex3f_vertexbuffer = NULL;
7998         rsurface.batchvertex3f_bufferoffset = 0;
7999         rsurface.batchsvector3f = NULL;
8000         rsurface.batchsvector3f_vertexbuffer = NULL;
8001         rsurface.batchsvector3f_bufferoffset = 0;
8002         rsurface.batchtvector3f = NULL;
8003         rsurface.batchtvector3f_vertexbuffer = NULL;
8004         rsurface.batchtvector3f_bufferoffset = 0;
8005         rsurface.batchnormal3f  = NULL;
8006         rsurface.batchnormal3f_vertexbuffer = NULL;
8007         rsurface.batchnormal3f_bufferoffset = 0;
8008         rsurface.batchlightmapcolor4f = NULL;
8009         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8010         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8011         rsurface.batchtexcoordtexture2f = NULL;
8012         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8013         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8014         rsurface.batchtexcoordlightmap2f = NULL;
8015         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8016         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8017         rsurface.batchvertexmesh = NULL;
8018         rsurface.batchvertexmeshbuffer = NULL;
8019         rsurface.batchvertex3fbuffer = NULL;
8020         rsurface.batchelement3i = NULL;
8021         rsurface.batchelement3i_indexbuffer = NULL;
8022         rsurface.batchelement3i_bufferoffset = 0;
8023         rsurface.batchelement3s = NULL;
8024         rsurface.batchelement3s_indexbuffer = NULL;
8025         rsurface.batchelement3s_bufferoffset = 0;
8026         rsurface.passcolor4f = NULL;
8027         rsurface.passcolor4f_vertexbuffer = NULL;
8028         rsurface.passcolor4f_bufferoffset = 0;
8029 }
8030
8031 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)
8032 {
8033         rsurface.entity = r_refdef.scene.worldentity;
8034         rsurface.skeleton = NULL;
8035         rsurface.ent_skinnum = 0;
8036         rsurface.ent_qwskin = -1;
8037         rsurface.ent_shadertime = shadertime;
8038         rsurface.ent_flags = entflags;
8039         rsurface.modelnumvertices = numvertices;
8040         rsurface.modelnumtriangles = numtriangles;
8041         rsurface.matrix = *matrix;
8042         rsurface.inversematrix = *inversematrix;
8043         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8044         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8045         R_EntityMatrix(&rsurface.matrix);
8046         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8047         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8048         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8049         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8050         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8051         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8052         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8053         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8054         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8055         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8056         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8057         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8058         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);
8059         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8060         rsurface.frameblend[0].lerp = 1;
8061         rsurface.ent_alttextures = false;
8062         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8063         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8064         if (wanttangents)
8065         {
8066                 rsurface.modelvertex3f = (float *)vertex3f;
8067                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8069                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8070         }
8071         else if (wantnormals)
8072         {
8073                 rsurface.modelvertex3f = (float *)vertex3f;
8074                 rsurface.modelsvector3f = NULL;
8075                 rsurface.modeltvector3f = NULL;
8076                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8077         }
8078         else
8079         {
8080                 rsurface.modelvertex3f = (float *)vertex3f;
8081                 rsurface.modelsvector3f = NULL;
8082                 rsurface.modeltvector3f = NULL;
8083                 rsurface.modelnormal3f = NULL;
8084         }
8085         rsurface.modelvertexmesh = NULL;
8086         rsurface.modelvertexmeshbuffer = NULL;
8087         rsurface.modelvertex3fbuffer = NULL;
8088         rsurface.modelvertex3f_vertexbuffer = 0;
8089         rsurface.modelvertex3f_bufferoffset = 0;
8090         rsurface.modelsvector3f_vertexbuffer = 0;
8091         rsurface.modelsvector3f_bufferoffset = 0;
8092         rsurface.modeltvector3f_vertexbuffer = 0;
8093         rsurface.modeltvector3f_bufferoffset = 0;
8094         rsurface.modelnormal3f_vertexbuffer = 0;
8095         rsurface.modelnormal3f_bufferoffset = 0;
8096         rsurface.modelgeneratedvertex = true;
8097         rsurface.modellightmapcolor4f  = (float *)color4f;
8098         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8099         rsurface.modellightmapcolor4f_bufferoffset = 0;
8100         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8101         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8102         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8103         rsurface.modeltexcoordlightmap2f  = NULL;
8104         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8105         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8106         rsurface.modelelement3i = (int *)element3i;
8107         rsurface.modelelement3i_indexbuffer = NULL;
8108         rsurface.modelelement3i_bufferoffset = 0;
8109         rsurface.modelelement3s = (unsigned short *)element3s;
8110         rsurface.modelelement3s_indexbuffer = NULL;
8111         rsurface.modelelement3s_bufferoffset = 0;
8112         rsurface.modellightmapoffsets = NULL;
8113         rsurface.modelsurfaces = NULL;
8114         rsurface.batchgeneratedvertex = false;
8115         rsurface.batchfirstvertex = 0;
8116         rsurface.batchnumvertices = 0;
8117         rsurface.batchfirsttriangle = 0;
8118         rsurface.batchnumtriangles = 0;
8119         rsurface.batchvertex3f  = NULL;
8120         rsurface.batchvertex3f_vertexbuffer = NULL;
8121         rsurface.batchvertex3f_bufferoffset = 0;
8122         rsurface.batchsvector3f = NULL;
8123         rsurface.batchsvector3f_vertexbuffer = NULL;
8124         rsurface.batchsvector3f_bufferoffset = 0;
8125         rsurface.batchtvector3f = NULL;
8126         rsurface.batchtvector3f_vertexbuffer = NULL;
8127         rsurface.batchtvector3f_bufferoffset = 0;
8128         rsurface.batchnormal3f  = NULL;
8129         rsurface.batchnormal3f_vertexbuffer = NULL;
8130         rsurface.batchnormal3f_bufferoffset = 0;
8131         rsurface.batchlightmapcolor4f = NULL;
8132         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8133         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8134         rsurface.batchtexcoordtexture2f = NULL;
8135         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8136         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8137         rsurface.batchtexcoordlightmap2f = NULL;
8138         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8139         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8140         rsurface.batchvertexmesh = NULL;
8141         rsurface.batchvertexmeshbuffer = NULL;
8142         rsurface.batchvertex3fbuffer = NULL;
8143         rsurface.batchelement3i = NULL;
8144         rsurface.batchelement3i_indexbuffer = NULL;
8145         rsurface.batchelement3i_bufferoffset = 0;
8146         rsurface.batchelement3s = NULL;
8147         rsurface.batchelement3s_indexbuffer = NULL;
8148         rsurface.batchelement3s_bufferoffset = 0;
8149         rsurface.passcolor4f = NULL;
8150         rsurface.passcolor4f_vertexbuffer = NULL;
8151         rsurface.passcolor4f_bufferoffset = 0;
8152
8153         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8154         {
8155                 if ((wantnormals || wanttangents) && !normal3f)
8156                 {
8157                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8158                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8159                 }
8160                 if (wanttangents && !svector3f)
8161                 {
8162                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8164                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8165                 }
8166         }
8167 }
8168
8169 float RSurf_FogPoint(const float *v)
8170 {
8171         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8172         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8173         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8174         float FogHeightFade = r_refdef.fogheightfade;
8175         float fogfrac;
8176         unsigned int fogmasktableindex;
8177         if (r_refdef.fogplaneviewabove)
8178                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8179         else
8180                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8181         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8182         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8183 }
8184
8185 float RSurf_FogVertex(const float *v)
8186 {
8187         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8188         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8189         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8190         float FogHeightFade = rsurface.fogheightfade;
8191         float fogfrac;
8192         unsigned int fogmasktableindex;
8193         if (r_refdef.fogplaneviewabove)
8194                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8195         else
8196                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8197         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8198         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8199 }
8200
8201 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8202 {
8203         int i;
8204         for (i = 0;i < numelements;i++)
8205                 outelement3i[i] = inelement3i[i] + adjust;
8206 }
8207
8208 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8209 extern cvar_t gl_vbo;
8210 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8211 {
8212         int deformindex;
8213         int firsttriangle;
8214         int numtriangles;
8215         int firstvertex;
8216         int endvertex;
8217         int numvertices;
8218         int surfacefirsttriangle;
8219         int surfacenumtriangles;
8220         int surfacefirstvertex;
8221         int surfaceendvertex;
8222         int surfacenumvertices;
8223         int batchnumvertices;
8224         int batchnumtriangles;
8225         int needsupdate;
8226         int i, j;
8227         qboolean gaps;
8228         qboolean dynamicvertex;
8229         float amplitude;
8230         float animpos;
8231         float scale;
8232         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8233         float waveparms[4];
8234         q3shaderinfo_deform_t *deform;
8235         const msurface_t *surface, *firstsurface;
8236         r_vertexmesh_t *vertexmesh;
8237         if (!texturenumsurfaces)
8238                 return;
8239         // find vertex range of this surface batch
8240         gaps = false;
8241         firstsurface = texturesurfacelist[0];
8242         firsttriangle = firstsurface->num_firsttriangle;
8243         batchnumvertices = 0;
8244         batchnumtriangles = 0;
8245         firstvertex = endvertex = firstsurface->num_firstvertex;
8246         for (i = 0;i < texturenumsurfaces;i++)
8247         {
8248                 surface = texturesurfacelist[i];
8249                 if (surface != firstsurface + i)
8250                         gaps = true;
8251                 surfacefirstvertex = surface->num_firstvertex;
8252                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8253                 surfacenumvertices = surface->num_vertices;
8254                 surfacenumtriangles = surface->num_triangles;
8255                 if (firstvertex > surfacefirstvertex)
8256                         firstvertex = surfacefirstvertex;
8257                 if (endvertex < surfaceendvertex)
8258                         endvertex = surfaceendvertex;
8259                 batchnumvertices += surfacenumvertices;
8260                 batchnumtriangles += surfacenumtriangles;
8261         }
8262
8263         // we now know the vertex range used, and if there are any gaps in it
8264         rsurface.batchfirstvertex = firstvertex;
8265         rsurface.batchnumvertices = endvertex - firstvertex;
8266         rsurface.batchfirsttriangle = firsttriangle;
8267         rsurface.batchnumtriangles = batchnumtriangles;
8268
8269         // this variable holds flags for which properties have been updated that
8270         // may require regenerating vertexmesh array...
8271         needsupdate = 0;
8272
8273         // check if any dynamic vertex processing must occur
8274         dynamicvertex = false;
8275
8276         // if there is a chance of animated vertex colors, it's a dynamic batch
8277         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8278         {
8279                 dynamicvertex = true;
8280                 batchneed |= BATCHNEED_NOGAPS;
8281                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8282         }
8283
8284         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8285         {
8286                 switch (deform->deform)
8287                 {
8288                 default:
8289                 case Q3DEFORM_PROJECTIONSHADOW:
8290                 case Q3DEFORM_TEXT0:
8291                 case Q3DEFORM_TEXT1:
8292                 case Q3DEFORM_TEXT2:
8293                 case Q3DEFORM_TEXT3:
8294                 case Q3DEFORM_TEXT4:
8295                 case Q3DEFORM_TEXT5:
8296                 case Q3DEFORM_TEXT6:
8297                 case Q3DEFORM_TEXT7:
8298                 case Q3DEFORM_NONE:
8299                         break;
8300                 case Q3DEFORM_AUTOSPRITE:
8301                         dynamicvertex = true;
8302                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8303                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8304                         break;
8305                 case Q3DEFORM_AUTOSPRITE2:
8306                         dynamicvertex = true;
8307                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8309                         break;
8310                 case Q3DEFORM_NORMAL:
8311                         dynamicvertex = true;
8312                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8314                         break;
8315                 case Q3DEFORM_WAVE:
8316                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8317                                 break; // if wavefunc is a nop, ignore this transform
8318                         dynamicvertex = true;
8319                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8320                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8321                         break;
8322                 case Q3DEFORM_BULGE:
8323                         dynamicvertex = true;
8324                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8326                         break;
8327                 case Q3DEFORM_MOVE:
8328                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8329                                 break; // if wavefunc is a nop, ignore this transform
8330                         dynamicvertex = true;
8331                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8332                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8333                         break;
8334                 }
8335         }
8336         switch(rsurface.texture->tcgen.tcgen)
8337         {
8338         default:
8339         case Q3TCGEN_TEXTURE:
8340                 break;
8341         case Q3TCGEN_LIGHTMAP:
8342                 dynamicvertex = true;
8343                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8344                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8345                 break;
8346         case Q3TCGEN_VECTOR:
8347                 dynamicvertex = true;
8348                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8349                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8350                 break;
8351         case Q3TCGEN_ENVIRONMENT:
8352                 dynamicvertex = true;
8353                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8354                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8355                 break;
8356         }
8357         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8358         {
8359                 dynamicvertex = true;
8360                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8361                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8362         }
8363
8364         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8365         {
8366                 dynamicvertex = true;
8367                 batchneed |= BATCHNEED_NOGAPS;
8368                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8369         }
8370
8371         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8372         {
8373                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8374                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8375                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8376                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8377                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8378                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8379                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8380         }
8381
8382         // when the model data has no vertex buffer (dynamic mesh), we need to
8383         // eliminate gaps
8384         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8385                 batchneed |= BATCHNEED_NOGAPS;
8386
8387         // if needsupdate, we have to do a dynamic vertex batch for sure
8388         if (needsupdate & batchneed)
8389                 dynamicvertex = true;
8390
8391         // see if we need to build vertexmesh from arrays
8392         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8393                 dynamicvertex = true;
8394
8395         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8396         // also some drivers strongly dislike firstvertex
8397         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8398                 dynamicvertex = true;
8399
8400         rsurface.batchvertex3f = rsurface.modelvertex3f;
8401         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8402         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8403         rsurface.batchsvector3f = rsurface.modelsvector3f;
8404         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8405         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8406         rsurface.batchtvector3f = rsurface.modeltvector3f;
8407         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8408         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8409         rsurface.batchnormal3f = rsurface.modelnormal3f;
8410         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8411         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8412         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8413         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8414         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8415         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8416         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8417         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8418         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8419         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8420         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8421         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8422         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8423         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8424         rsurface.batchelement3i = rsurface.modelelement3i;
8425         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8426         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8427         rsurface.batchelement3s = rsurface.modelelement3s;
8428         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8429         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8430
8431         // if any dynamic vertex processing has to occur in software, we copy the
8432         // entire surface list together before processing to rebase the vertices
8433         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8434         //
8435         // if any gaps exist and we do not have a static vertex buffer, we have to
8436         // copy the surface list together to avoid wasting upload bandwidth on the
8437         // vertices in the gaps.
8438         //
8439         // if gaps exist and we have a static vertex buffer, we still have to
8440         // combine the index buffer ranges into one dynamic index buffer.
8441         //
8442         // in all cases we end up with data that can be drawn in one call.
8443
8444         if (!dynamicvertex)
8445         {
8446                 // static vertex data, just set pointers...
8447                 rsurface.batchgeneratedvertex = false;
8448                 // if there are gaps, we want to build a combined index buffer,
8449                 // otherwise use the original static buffer with an appropriate offset
8450                 if (gaps)
8451                 {
8452                         // build a new triangle elements array for this batch
8453                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8454                         rsurface.batchfirsttriangle = 0;
8455                         numtriangles = 0;
8456                         for (i = 0;i < texturenumsurfaces;i++)
8457                         {
8458                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8459                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8460                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8461                                 numtriangles += surfacenumtriangles;
8462                         }
8463                         rsurface.batchelement3i_indexbuffer = NULL;
8464                         rsurface.batchelement3i_bufferoffset = 0;
8465                         rsurface.batchelement3s = NULL;
8466                         rsurface.batchelement3s_indexbuffer = NULL;
8467                         rsurface.batchelement3s_bufferoffset = 0;
8468                         if (endvertex <= 65536)
8469                         {
8470                                 // make a 16bit (unsigned short) index array if possible
8471                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8472                                 for (i = 0;i < numtriangles*3;i++)
8473                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8474                         }
8475                 }
8476                 return;
8477         }
8478
8479         // something needs software processing, do it for real...
8480         // we only directly handle separate array data in this case and then
8481         // generate interleaved data if needed...
8482         rsurface.batchgeneratedvertex = true;
8483
8484         // now copy the vertex data into a combined array and make an index array
8485         // (this is what Quake3 does all the time)
8486         //if (gaps || rsurface.batchfirstvertex)
8487         {
8488                 rsurface.batchvertex3fbuffer = NULL;
8489                 rsurface.batchvertexmesh = NULL;
8490                 rsurface.batchvertexmeshbuffer = NULL;
8491                 rsurface.batchvertex3f = NULL;
8492                 rsurface.batchvertex3f_vertexbuffer = NULL;
8493                 rsurface.batchvertex3f_bufferoffset = 0;
8494                 rsurface.batchsvector3f = NULL;
8495                 rsurface.batchsvector3f_vertexbuffer = NULL;
8496                 rsurface.batchsvector3f_bufferoffset = 0;
8497                 rsurface.batchtvector3f = NULL;
8498                 rsurface.batchtvector3f_vertexbuffer = NULL;
8499                 rsurface.batchtvector3f_bufferoffset = 0;
8500                 rsurface.batchnormal3f = NULL;
8501                 rsurface.batchnormal3f_vertexbuffer = NULL;
8502                 rsurface.batchnormal3f_bufferoffset = 0;
8503                 rsurface.batchlightmapcolor4f = NULL;
8504                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8505                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8506                 rsurface.batchtexcoordtexture2f = NULL;
8507                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8508                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8509                 rsurface.batchtexcoordlightmap2f = NULL;
8510                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8511                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8512                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8513                 rsurface.batchelement3i_indexbuffer = NULL;
8514                 rsurface.batchelement3i_bufferoffset = 0;
8515                 rsurface.batchelement3s = NULL;
8516                 rsurface.batchelement3s_indexbuffer = NULL;
8517                 rsurface.batchelement3s_bufferoffset = 0;
8518                 // we'll only be setting up certain arrays as needed
8519                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8520                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8521                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8522                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8524                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8525                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8526                 {
8527                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8529                 }
8530                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8531                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8532                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8533                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8535                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8536                 numvertices = 0;
8537                 numtriangles = 0;
8538                 for (i = 0;i < texturenumsurfaces;i++)
8539                 {
8540                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8541                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8542                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8543                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8544                         // copy only the data requested
8545                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8546                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8547                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8548                         {
8549                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8550                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8552                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8553                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8554                                 {
8555                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8557                                 }
8558                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8559                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8560                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8561                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8562                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8563                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8564                         }
8565                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8566                         numvertices += surfacenumvertices;
8567                         numtriangles += surfacenumtriangles;
8568                 }
8569
8570                 // generate a 16bit index array as well if possible
8571                 // (in general, dynamic batches fit)
8572                 if (numvertices <= 65536)
8573                 {
8574                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575                         for (i = 0;i < numtriangles*3;i++)
8576                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8577                 }
8578
8579                 // since we've copied everything, the batch now starts at 0
8580                 rsurface.batchfirstvertex = 0;
8581                 rsurface.batchnumvertices = batchnumvertices;
8582                 rsurface.batchfirsttriangle = 0;
8583                 rsurface.batchnumtriangles = batchnumtriangles;
8584         }
8585
8586         // q1bsp surfaces rendered in vertex color mode have to have colors
8587         // calculated based on lightstyles
8588         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8589         {
8590                 // generate color arrays for the surfaces in this list
8591                 int c[4];
8592                 int scale;
8593                 int size3;
8594                 const int *offsets;
8595                 const unsigned char *lm;
8596                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8597                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8599                 numvertices = 0;
8600                 for (i = 0;i < texturenumsurfaces;i++)
8601                 {
8602                         surface = texturesurfacelist[i];
8603                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8604                         surfacenumvertices = surface->num_vertices;
8605                         if (surface->lightmapinfo->samples)
8606                         {
8607                                 for (j = 0;j < surfacenumvertices;j++)
8608                                 {
8609                                         lm = surface->lightmapinfo->samples + offsets[j];
8610                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8611                                         VectorScale(lm, scale, c);
8612                                         if (surface->lightmapinfo->styles[1] != 255)
8613                                         {
8614                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8615                                                 lm += size3;
8616                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8617                                                 VectorMA(c, scale, lm, c);
8618                                                 if (surface->lightmapinfo->styles[2] != 255)
8619                                                 {
8620                                                         lm += size3;
8621                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8622                                                         VectorMA(c, scale, lm, c);
8623                                                         if (surface->lightmapinfo->styles[3] != 255)
8624                                                         {
8625                                                                 lm += size3;
8626                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8627                                                                 VectorMA(c, scale, lm, c);
8628                                                         }
8629                                                 }
8630                                         }
8631                                         c[0] >>= 7;
8632                                         c[1] >>= 7;
8633                                         c[2] >>= 7;
8634                                         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);
8635                                         numvertices++;
8636                                 }
8637                         }
8638                         else
8639                         {
8640                                 for (j = 0;j < surfacenumvertices;j++)
8641                                 {
8642                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8643                                         numvertices++;
8644                                 }
8645                         }
8646                 }
8647         }
8648
8649         // if vertices are deformed (sprite flares and things in maps, possibly
8650         // water waves, bulges and other deformations), modify the copied vertices
8651         // in place
8652         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8653         {
8654                 switch (deform->deform)
8655                 {
8656                 default:
8657                 case Q3DEFORM_PROJECTIONSHADOW:
8658                 case Q3DEFORM_TEXT0:
8659                 case Q3DEFORM_TEXT1:
8660                 case Q3DEFORM_TEXT2:
8661                 case Q3DEFORM_TEXT3:
8662                 case Q3DEFORM_TEXT4:
8663                 case Q3DEFORM_TEXT5:
8664                 case Q3DEFORM_TEXT6:
8665                 case Q3DEFORM_TEXT7:
8666                 case Q3DEFORM_NONE:
8667                         break;
8668                 case Q3DEFORM_AUTOSPRITE:
8669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672                         VectorNormalize(newforward);
8673                         VectorNormalize(newright);
8674                         VectorNormalize(newup);
8675 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8677 //                      rsurface.batchvertex3f_bufferoffset = 0;
8678 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8679 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8680 //                      rsurface.batchsvector3f_bufferoffset = 0;
8681 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8682 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8683 //                      rsurface.batchtvector3f_bufferoffset = 0;
8684 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8686 //                      rsurface.batchnormal3f_bufferoffset = 0;
8687                         // a single autosprite surface can contain multiple sprites...
8688                         for (j = 0;j < batchnumvertices - 3;j += 4)
8689                         {
8690                                 VectorClear(center);
8691                                 for (i = 0;i < 4;i++)
8692                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8693                                 VectorScale(center, 0.25f, center);
8694                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8695                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8696                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8697                                 for (i = 0;i < 4;i++)
8698                                 {
8699                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8700                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8701                                 }
8702                         }
8703                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8704                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8705                         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);
8706                         break;
8707                 case Q3DEFORM_AUTOSPRITE2:
8708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8709                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8710                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8711                         VectorNormalize(newforward);
8712                         VectorNormalize(newright);
8713                         VectorNormalize(newup);
8714 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8715 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8716 //                      rsurface.batchvertex3f_bufferoffset = 0;
8717                         {
8718                                 const float *v1, *v2;
8719                                 vec3_t start, end;
8720                                 float f, l;
8721                                 struct
8722                                 {
8723                                         float length2;
8724                                         const float *v1;
8725                                         const float *v2;
8726                                 }
8727                                 shortest[2];
8728                                 memset(shortest, 0, sizeof(shortest));
8729                                 // a single autosprite surface can contain multiple sprites...
8730                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8731                                 {
8732                                         VectorClear(center);
8733                                         for (i = 0;i < 4;i++)
8734                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8735                                         VectorScale(center, 0.25f, center);
8736                                         // find the two shortest edges, then use them to define the
8737                                         // axis vectors for rotating around the central axis
8738                                         for (i = 0;i < 6;i++)
8739                                         {
8740                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8741                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8742                                                 l = VectorDistance2(v1, v2);
8743                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8744                                                 if (v1[2] != v2[2])
8745                                                         l += (1.0f / 1024.0f);
8746                                                 if (shortest[0].length2 > l || i == 0)
8747                                                 {
8748                                                         shortest[1] = shortest[0];
8749                                                         shortest[0].length2 = l;
8750                                                         shortest[0].v1 = v1;
8751                                                         shortest[0].v2 = v2;
8752                                                 }
8753                                                 else if (shortest[1].length2 > l || i == 1)
8754                                                 {
8755                                                         shortest[1].length2 = l;
8756                                                         shortest[1].v1 = v1;
8757                                                         shortest[1].v2 = v2;
8758                                                 }
8759                                         }
8760                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8761                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8762                                         // this calculates the right vector from the shortest edge
8763                                         // and the up vector from the edge midpoints
8764                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8765                                         VectorNormalize(right);
8766                                         VectorSubtract(end, start, up);
8767                                         VectorNormalize(up);
8768                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8769                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8770                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8771                                         VectorNegate(forward, forward);
8772                                         VectorReflect(forward, 0, up, forward);
8773                                         VectorNormalize(forward);
8774                                         CrossProduct(up, forward, newright);
8775                                         VectorNormalize(newright);
8776                                         // rotate the quad around the up axis vector, this is made
8777                                         // especially easy by the fact we know the quad is flat,
8778                                         // so we only have to subtract the center position and
8779                                         // measure distance along the right vector, and then
8780                                         // multiply that by the newright vector and add back the
8781                                         // center position
8782                                         // we also need to subtract the old position to undo the
8783                                         // displacement from the center, which we do with a
8784                                         // DotProduct, the subtraction/addition of center is also
8785                                         // optimized into DotProducts here
8786                                         l = DotProduct(right, center);
8787                                         for (i = 0;i < 4;i++)
8788                                         {
8789                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8790                                                 f = DotProduct(right, v1) - l;
8791                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8792                                         }
8793                                 }
8794                         }
8795                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8796                         {
8797 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8799 //                              rsurface.batchnormal3f_bufferoffset = 0;
8800                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8801                         }
8802                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8803                         {
8804 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8806 //                              rsurface.batchsvector3f_bufferoffset = 0;
8807 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8809 //                              rsurface.batchtvector3f_bufferoffset = 0;
8810                                 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);
8811                         }
8812                         break;
8813                 case Q3DEFORM_NORMAL:
8814                         // deform the normals to make reflections wavey
8815                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8816                         rsurface.batchnormal3f_vertexbuffer = NULL;
8817                         rsurface.batchnormal3f_bufferoffset = 0;
8818                         for (j = 0;j < batchnumvertices;j++)
8819                         {
8820                                 float vertex[3];
8821                                 float *normal = rsurface.batchnormal3f + 3*j;
8822                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8823                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8824                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8825                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8826                                 VectorNormalize(normal);
8827                         }
8828                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8829                         {
8830 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8831 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8832 //                              rsurface.batchsvector3f_bufferoffset = 0;
8833 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8835 //                              rsurface.batchtvector3f_bufferoffset = 0;
8836                                 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);
8837                         }
8838                         break;
8839                 case Q3DEFORM_WAVE:
8840                         // deform vertex array to make wavey water and flags and such
8841                         waveparms[0] = deform->waveparms[0];
8842                         waveparms[1] = deform->waveparms[1];
8843                         waveparms[2] = deform->waveparms[2];
8844                         waveparms[3] = deform->waveparms[3];
8845                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8846                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8847                         // this is how a divisor of vertex influence on deformation
8848                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8849                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8850 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8851 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8852 //                      rsurface.batchvertex3f_bufferoffset = 0;
8853 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8854 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8855 //                      rsurface.batchnormal3f_bufferoffset = 0;
8856                         for (j = 0;j < batchnumvertices;j++)
8857                         {
8858                                 // if the wavefunc depends on time, evaluate it per-vertex
8859                                 if (waveparms[3])
8860                                 {
8861                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8862                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8863                                 }
8864                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8865                         }
8866                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8867                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8868                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8869                         {
8870 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8872 //                              rsurface.batchsvector3f_bufferoffset = 0;
8873 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8875 //                              rsurface.batchtvector3f_bufferoffset = 0;
8876                                 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);
8877                         }
8878                         break;
8879                 case Q3DEFORM_BULGE:
8880                         // deform vertex array to make the surface have moving bulges
8881 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8882 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8883 //                      rsurface.batchvertex3f_bufferoffset = 0;
8884 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8885 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8886 //                      rsurface.batchnormal3f_bufferoffset = 0;
8887                         for (j = 0;j < batchnumvertices;j++)
8888                         {
8889                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8890                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8891                         }
8892                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8893                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8894                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8895                         {
8896 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8897 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8898 //                              rsurface.batchsvector3f_bufferoffset = 0;
8899 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
8901 //                              rsurface.batchtvector3f_bufferoffset = 0;
8902                                 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);
8903                         }
8904                         break;
8905                 case Q3DEFORM_MOVE:
8906                         // deform vertex array
8907                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8908                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
8909                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8910                         VectorScale(deform->parms, scale, waveparms);
8911 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8912 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8913 //                      rsurface.batchvertex3f_bufferoffset = 0;
8914                         for (j = 0;j < batchnumvertices;j++)
8915                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8916                         break;
8917                 }
8918         }
8919
8920         // generate texcoords based on the chosen texcoord source
8921         switch(rsurface.texture->tcgen.tcgen)
8922         {
8923         default:
8924         case Q3TCGEN_TEXTURE:
8925                 break;
8926         case Q3TCGEN_LIGHTMAP:
8927 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8928 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930                 if (rsurface.batchtexcoordlightmap2f)
8931                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8932                 break;
8933         case Q3TCGEN_VECTOR:
8934 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8935 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8936 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8937                 for (j = 0;j < batchnumvertices;j++)
8938                 {
8939                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8940                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8941                 }
8942                 break;
8943         case Q3TCGEN_ENVIRONMENT:
8944                 // make environment reflections using a spheremap
8945                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948                 for (j = 0;j < batchnumvertices;j++)
8949                 {
8950                         // identical to Q3A's method, but executed in worldspace so
8951                         // carried models can be shiny too
8952
8953                         float viewer[3], d, reflected[3], worldreflected[3];
8954
8955                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8956                         // VectorNormalize(viewer);
8957
8958                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8959
8960                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8961                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8962                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8963                         // note: this is proportinal to viewer, so we can normalize later
8964
8965                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8966                         VectorNormalize(worldreflected);
8967
8968                         // note: this sphere map only uses world x and z!
8969                         // so positive and negative y will LOOK THE SAME.
8970                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8971                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8972                 }
8973                 break;
8974         }
8975         // the only tcmod that needs software vertex processing is turbulent, so
8976         // check for it here and apply the changes if needed
8977         // and we only support that as the first one
8978         // (handling a mixture of turbulent and other tcmods would be problematic
8979         //  without punting it entirely to a software path)
8980         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8981         {
8982                 amplitude = rsurface.texture->tcmods[0].parms[1];
8983                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8984 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8985 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8986 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8987                 for (j = 0;j < batchnumvertices;j++)
8988                 {
8989                         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);
8990                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8991                 }
8992         }
8993
8994         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8995         {
8996                 // convert the modified arrays to vertex structs
8997 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8998 //              rsurface.batchvertexmeshbuffer = NULL;
8999                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9000                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9001                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9002                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9003                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9005                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9006                 {
9007                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9008                         {
9009                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9010                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9011                         }
9012                 }
9013                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9014                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9016                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9017                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9018                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9019                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9020                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9021                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9022         }
9023 }
9024
9025 void RSurf_DrawBatch(void)
9026 {
9027         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9028         // through the pipeline, killing it earlier in the pipeline would have
9029         // per-surface overhead rather than per-batch overhead, so it's best to
9030         // reject it here, before it hits glDraw.
9031         if (rsurface.batchnumtriangles == 0)
9032                 return;
9033 #if 0
9034         // batch debugging code
9035         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9036         {
9037                 int i;
9038                 int j;
9039                 int c;
9040                 const int *e;
9041                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9042                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9043                 {
9044                         c = e[i];
9045                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9046                         {
9047                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9048                                 {
9049                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9050                                                 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);
9051                                         break;
9052                                 }
9053                         }
9054                 }
9055         }
9056 #endif
9057         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);
9058 }
9059
9060 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9061 {
9062         // pick the closest matching water plane
9063         int planeindex, vertexindex, bestplaneindex = -1;
9064         float d, bestd;
9065         vec3_t vert;
9066         const float *v;
9067         r_waterstate_waterplane_t *p;
9068         qboolean prepared = false;
9069         bestd = 0;
9070         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9071         {
9072                 if(p->camera_entity != rsurface.texture->camera_entity)
9073                         continue;
9074                 d = 0;
9075                 if(!prepared)
9076                 {
9077                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9078                         prepared = true;
9079                         if(rsurface.batchnumvertices == 0)
9080                                 break;
9081                 }
9082                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9083                 {
9084                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9085                         d += fabs(PlaneDiff(vert, &p->plane));
9086                 }
9087                 if (bestd > d || bestplaneindex < 0)
9088                 {
9089                         bestd = d;
9090                         bestplaneindex = planeindex;
9091                 }
9092         }
9093         return bestplaneindex;
9094         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9095         // this situation though, as it might be better to render single larger
9096         // batches with useless stuff (backface culled for example) than to
9097         // render multiple smaller batches
9098 }
9099
9100 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9101 {
9102         int i;
9103         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9104         rsurface.passcolor4f_vertexbuffer = 0;
9105         rsurface.passcolor4f_bufferoffset = 0;
9106         for (i = 0;i < rsurface.batchnumvertices;i++)
9107                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9108 }
9109
9110 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9111 {
9112         int i;
9113         float f;
9114         const float *v;
9115         const float *c;
9116         float *c2;
9117         if (rsurface.passcolor4f)
9118         {
9119                 // generate color arrays
9120                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9121                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9122                 rsurface.passcolor4f_vertexbuffer = 0;
9123                 rsurface.passcolor4f_bufferoffset = 0;
9124                 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)
9125                 {
9126                         f = RSurf_FogVertex(v);
9127                         c2[0] = c[0] * f;
9128                         c2[1] = c[1] * f;
9129                         c2[2] = c[2] * f;
9130                         c2[3] = c[3];
9131                 }
9132         }
9133         else
9134         {
9135                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9136                 rsurface.passcolor4f_vertexbuffer = 0;
9137                 rsurface.passcolor4f_bufferoffset = 0;
9138                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9139                 {
9140                         f = RSurf_FogVertex(v);
9141                         c2[0] = f;
9142                         c2[1] = f;
9143                         c2[2] = f;
9144                         c2[3] = 1;
9145                 }
9146         }
9147 }
9148
9149 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9150 {
9151         int i;
9152         float f;
9153         const float *v;
9154         const float *c;
9155         float *c2;
9156         if (!rsurface.passcolor4f)
9157                 return;
9158         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9159         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9160         rsurface.passcolor4f_vertexbuffer = 0;
9161         rsurface.passcolor4f_bufferoffset = 0;
9162         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)
9163         {
9164                 f = RSurf_FogVertex(v);
9165                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9166                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9167                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9168                 c2[3] = c[3];
9169         }
9170 }
9171
9172 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9173 {
9174         int i;
9175         const float *c;
9176         float *c2;
9177         if (!rsurface.passcolor4f)
9178                 return;
9179         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9180         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9181         rsurface.passcolor4f_vertexbuffer = 0;
9182         rsurface.passcolor4f_bufferoffset = 0;
9183         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9184         {
9185                 c2[0] = c[0] * r;
9186                 c2[1] = c[1] * g;
9187                 c2[2] = c[2] * b;
9188                 c2[3] = c[3] * a;
9189         }
9190 }
9191
9192 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9193 {
9194         int i;
9195         const float *c;
9196         float *c2;
9197         if (!rsurface.passcolor4f)
9198                 return;
9199         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9200         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9201         rsurface.passcolor4f_vertexbuffer = 0;
9202         rsurface.passcolor4f_bufferoffset = 0;
9203         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9204         {
9205                 c2[0] = c[0] + r_refdef.scene.ambient;
9206                 c2[1] = c[1] + r_refdef.scene.ambient;
9207                 c2[2] = c[2] + r_refdef.scene.ambient;
9208                 c2[3] = c[3];
9209         }
9210 }
9211
9212 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9213 {
9214         // TODO: optimize
9215         rsurface.passcolor4f = NULL;
9216         rsurface.passcolor4f_vertexbuffer = 0;
9217         rsurface.passcolor4f_bufferoffset = 0;
9218         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9219         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9220         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9221         GL_Color(r, g, b, a);
9222         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9223         RSurf_DrawBatch();
9224 }
9225
9226 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9227 {
9228         // TODO: optimize applyfog && applycolor case
9229         // just apply fog if necessary, and tint the fog color array if necessary
9230         rsurface.passcolor4f = NULL;
9231         rsurface.passcolor4f_vertexbuffer = 0;
9232         rsurface.passcolor4f_bufferoffset = 0;
9233         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9234         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9235         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9236         GL_Color(r, g, b, a);
9237         RSurf_DrawBatch();
9238 }
9239
9240 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9241 {
9242         // TODO: optimize
9243         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9244         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9245         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9246         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9247         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249         GL_Color(r, g, b, a);
9250         RSurf_DrawBatch();
9251 }
9252
9253 static void RSurf_DrawBatch_GL11_ClampColor(void)
9254 {
9255         int i;
9256         const float *c1;
9257         float *c2;
9258         if (!rsurface.passcolor4f)
9259                 return;
9260         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9261         {
9262                 c2[0] = bound(0.0f, c1[0], 1.0f);
9263                 c2[1] = bound(0.0f, c1[1], 1.0f);
9264                 c2[2] = bound(0.0f, c1[2], 1.0f);
9265                 c2[3] = bound(0.0f, c1[3], 1.0f);
9266         }
9267 }
9268
9269 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9270 {
9271         int i;
9272         float f;
9273         const float *v;
9274         const float *n;
9275         float *c;
9276         //vec3_t eyedir;
9277
9278         // fake shading
9279         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9280         rsurface.passcolor4f_vertexbuffer = 0;
9281         rsurface.passcolor4f_bufferoffset = 0;
9282         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)
9283         {
9284                 f = -DotProduct(r_refdef.view.forward, n);
9285                 f = max(0, f);
9286                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9287                 f *= r_refdef.lightmapintensity;
9288                 Vector4Set(c, f, f, f, 1);
9289         }
9290 }
9291
9292 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9293 {
9294         RSurf_DrawBatch_GL11_ApplyFakeLight();
9295         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9296         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9297         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9298         GL_Color(r, g, b, a);
9299         RSurf_DrawBatch();
9300 }
9301
9302 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9303 {
9304         int i;
9305         float f;
9306         float alpha;
9307         const float *v;
9308         const float *n;
9309         float *c;
9310         vec3_t ambientcolor;
9311         vec3_t diffusecolor;
9312         vec3_t lightdir;
9313         // TODO: optimize
9314         // model lighting
9315         VectorCopy(rsurface.modellight_lightdir, lightdir);
9316         f = 0.5f * r_refdef.lightmapintensity;
9317         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9318         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9319         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9320         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9321         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9322         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9323         alpha = *a;
9324         if (VectorLength2(diffusecolor) > 0)
9325         {
9326                 // q3-style directional shading
9327                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328                 rsurface.passcolor4f_vertexbuffer = 0;
9329                 rsurface.passcolor4f_bufferoffset = 0;
9330                 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)
9331                 {
9332                         if ((f = DotProduct(n, lightdir)) > 0)
9333                                 VectorMA(ambientcolor, f, diffusecolor, c);
9334                         else
9335                                 VectorCopy(ambientcolor, c);
9336                         c[3] = alpha;
9337                 }
9338                 *r = 1;
9339                 *g = 1;
9340                 *b = 1;
9341                 *a = 1;
9342                 *applycolor = false;
9343         }
9344         else
9345         {
9346                 *r = ambientcolor[0];
9347                 *g = ambientcolor[1];
9348                 *b = ambientcolor[2];
9349                 rsurface.passcolor4f = NULL;
9350                 rsurface.passcolor4f_vertexbuffer = 0;
9351                 rsurface.passcolor4f_bufferoffset = 0;
9352         }
9353 }
9354
9355 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9356 {
9357         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
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_MakeFogColor(float r, float g, float b, float a)
9366 {
9367         int i;
9368         float f;
9369         const float *v;
9370         float *c;
9371
9372         // fake shading
9373         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374         rsurface.passcolor4f_vertexbuffer = 0;
9375         rsurface.passcolor4f_bufferoffset = 0;
9376
9377         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9378         {
9379                 f = 1 - RSurf_FogVertex(v);
9380                 c[0] = r;
9381                 c[1] = g;
9382                 c[2] = b;
9383                 c[3] = f * a;
9384         }
9385 }
9386
9387 void RSurf_SetupDepthAndCulling(void)
9388 {
9389         // submodels are biased to avoid z-fighting with world surfaces that they
9390         // may be exactly overlapping (avoids z-fighting artifacts on certain
9391         // doors and things in Quake maps)
9392         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9393         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9394         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9395         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9396 }
9397
9398 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9399 {
9400         // transparent sky would be ridiculous
9401         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9402                 return;
9403         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9404         skyrenderlater = true;
9405         RSurf_SetupDepthAndCulling();
9406         GL_DepthMask(true);
9407         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9408         // skymasking on them, and Quake3 never did sky masking (unlike
9409         // software Quake and software Quake2), so disable the sky masking
9410         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9411         // and skymasking also looks very bad when noclipping outside the
9412         // level, so don't use it then either.
9413         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9414         {
9415                 R_Mesh_ResetTextureState();
9416                 if (skyrendermasked)
9417                 {
9418                         R_SetupShader_DepthOrShadow();
9419                         // depth-only (masking)
9420                         GL_ColorMask(0,0,0,0);
9421                         // just to make sure that braindead drivers don't draw
9422                         // anything despite that colormask...
9423                         GL_BlendFunc(GL_ZERO, GL_ONE);
9424                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425                         if (rsurface.batchvertex3fbuffer)
9426                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9427                         else
9428                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9429                 }
9430                 else
9431                 {
9432                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9433                         // fog sky
9434                         GL_BlendFunc(GL_ONE, GL_ZERO);
9435                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9437                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9438                 }
9439                 RSurf_DrawBatch();
9440                 if (skyrendermasked)
9441                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9442         }
9443         R_Mesh_ResetTextureState();
9444         GL_Color(1, 1, 1, 1);
9445 }
9446
9447 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9448 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9449 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9450 {
9451         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9452                 return;
9453         if (prepass)
9454         {
9455                 // render screenspace normalmap to texture
9456                 GL_DepthMask(true);
9457                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9458                 RSurf_DrawBatch();
9459         }
9460
9461         // bind lightmap texture
9462
9463         // water/refraction/reflection/camera surfaces have to be handled specially
9464         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9465         {
9466                 int start, end, startplaneindex;
9467                 for (start = 0;start < texturenumsurfaces;start = end)
9468                 {
9469                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9470                         if(startplaneindex < 0)
9471                         {
9472                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9473                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9474                                 end = start + 1;
9475                                 continue;
9476                         }
9477                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9478                                 ;
9479                         // now that we have a batch using the same planeindex, render it
9480                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9481                         {
9482                                 // render water or distortion background
9483                                 GL_DepthMask(true);
9484                                 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));
9485                                 RSurf_DrawBatch();
9486                                 // blend surface on top
9487                                 GL_DepthMask(false);
9488                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9489                                 RSurf_DrawBatch();
9490                         }
9491                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9492                         {
9493                                 // render surface with reflection texture as input
9494                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9495                                 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));
9496                                 RSurf_DrawBatch();
9497                         }
9498                 }
9499                 return;
9500         }
9501
9502         // render surface batch normally
9503         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9504         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9505         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9506                 GL_AlphaTest(true);
9507         RSurf_DrawBatch();
9508         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9509                 GL_AlphaTest(false);
9510 }
9511
9512 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9513 {
9514         // OpenGL 1.3 path - anything not completely ancient
9515         qboolean applycolor;
9516         qboolean applyfog;
9517         int layerindex;
9518         const texturelayer_t *layer;
9519         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);
9520         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9521
9522         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9523         {
9524                 vec4_t layercolor;
9525                 int layertexrgbscale;
9526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9527                 {
9528                         if (layerindex == 0)
9529                                 GL_AlphaTest(true);
9530                         else
9531                         {
9532                                 GL_AlphaTest(false);
9533                                 GL_DepthFunc(GL_EQUAL);
9534                         }
9535                 }
9536                 GL_DepthMask(layer->depthmask && writedepth);
9537                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9538                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9539                 {
9540                         layertexrgbscale = 4;
9541                         VectorScale(layer->color, 0.25f, layercolor);
9542                 }
9543                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9544                 {
9545                         layertexrgbscale = 2;
9546                         VectorScale(layer->color, 0.5f, layercolor);
9547                 }
9548                 else
9549                 {
9550                         layertexrgbscale = 1;
9551                         VectorScale(layer->color, 1.0f, layercolor);
9552                 }
9553                 layercolor[3] = layer->color[3];
9554                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9555                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9556                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9557                 switch (layer->type)
9558                 {
9559                 case TEXTURELAYERTYPE_LITTEXTURE:
9560                         // single-pass lightmapped texture with 2x rgbscale
9561                         R_Mesh_TexBind(0, r_texture_white);
9562                         R_Mesh_TexMatrix(0, NULL);
9563                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9564                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9565                         R_Mesh_TexBind(1, layer->texture);
9566                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9567                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9568                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9569                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9570                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9571                         else if (FAKELIGHT_ENABLED)
9572                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573                         else if (rsurface.uselightmaptexture)
9574                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9575                         else
9576                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9577                         break;
9578                 case TEXTURELAYERTYPE_TEXTURE:
9579                         // singletexture unlit texture with transparency support
9580                         R_Mesh_TexBind(0, layer->texture);
9581                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9582                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9583                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9584                         R_Mesh_TexBind(1, 0);
9585                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9586                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9587                         break;
9588                 case TEXTURELAYERTYPE_FOG:
9589                         // singletexture fogging
9590                         if (layer->texture)
9591                         {
9592                                 R_Mesh_TexBind(0, layer->texture);
9593                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9594                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9595                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9596                         }
9597                         else
9598                         {
9599                                 R_Mesh_TexBind(0, 0);
9600                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9601                         }
9602                         R_Mesh_TexBind(1, 0);
9603                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9604                         // generate a color array for the fog pass
9605                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9606                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9607                         RSurf_DrawBatch();
9608                         break;
9609                 default:
9610                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9611                 }
9612         }
9613         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9614         {
9615                 GL_DepthFunc(GL_LEQUAL);
9616                 GL_AlphaTest(false);
9617         }
9618 }
9619
9620 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9621 {
9622         // OpenGL 1.1 - crusty old voodoo path
9623         qboolean applyfog;
9624         int layerindex;
9625         const texturelayer_t *layer;
9626         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);
9627         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9628
9629         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9630         {
9631                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9632                 {
9633                         if (layerindex == 0)
9634                                 GL_AlphaTest(true);
9635                         else
9636                         {
9637                                 GL_AlphaTest(false);
9638                                 GL_DepthFunc(GL_EQUAL);
9639                         }
9640                 }
9641                 GL_DepthMask(layer->depthmask && writedepth);
9642                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9643                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9644                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9645                 switch (layer->type)
9646                 {
9647                 case TEXTURELAYERTYPE_LITTEXTURE:
9648                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9649                         {
9650                                 // two-pass lit texture with 2x rgbscale
9651                                 // first the lightmap pass
9652                                 R_Mesh_TexBind(0, r_texture_white);
9653                                 R_Mesh_TexMatrix(0, NULL);
9654                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9655                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9656                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9657                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9658                                 else if (FAKELIGHT_ENABLED)
9659                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9660                                 else if (rsurface.uselightmaptexture)
9661                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9662                                 else
9663                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9664                                 // then apply the texture to it
9665                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9666                                 R_Mesh_TexBind(0, layer->texture);
9667                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9668                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9669                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9670                                 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);
9671                         }
9672                         else
9673                         {
9674                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9675                                 R_Mesh_TexBind(0, layer->texture);
9676                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9677                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9678                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9679                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9680                                         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);
9681                                 else
9682                                         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);
9683                         }
9684                         break;
9685                 case TEXTURELAYERTYPE_TEXTURE:
9686                         // singletexture unlit texture with transparency support
9687                         R_Mesh_TexBind(0, layer->texture);
9688                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9689                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9691                         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);
9692                         break;
9693                 case TEXTURELAYERTYPE_FOG:
9694                         // singletexture fogging
9695                         if (layer->texture)
9696                         {
9697                                 R_Mesh_TexBind(0, layer->texture);
9698                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9699                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9700                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9701                         }
9702                         else
9703                         {
9704                                 R_Mesh_TexBind(0, 0);
9705                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9706                         }
9707                         // generate a color array for the fog pass
9708                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9709                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9710                         RSurf_DrawBatch();
9711                         break;
9712                 default:
9713                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9714                 }
9715         }
9716         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9717         {
9718                 GL_DepthFunc(GL_LEQUAL);
9719                 GL_AlphaTest(false);
9720         }
9721 }
9722
9723 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9724 {
9725         int vi;
9726         int j;
9727         r_vertexgeneric_t *batchvertex;
9728         float c[4];
9729
9730 //      R_Mesh_ResetTextureState();
9731         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9732
9733         if(rsurface.texture && rsurface.texture->currentskinframe)
9734         {
9735                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9736                 c[3] *= rsurface.texture->currentalpha;
9737         }
9738         else
9739         {
9740                 c[0] = 1;
9741                 c[1] = 0;
9742                 c[2] = 1;
9743                 c[3] = 1;
9744         }
9745
9746         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9747         {
9748                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9749                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9750                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9751         }
9752
9753         // brighten it up (as texture value 127 means "unlit")
9754         c[0] *= 2 * r_refdef.view.colorscale;
9755         c[1] *= 2 * r_refdef.view.colorscale;
9756         c[2] *= 2 * r_refdef.view.colorscale;
9757
9758         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9759                 c[3] *= r_wateralpha.value;
9760
9761         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9762         {
9763                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9764                 GL_DepthMask(false);
9765         }
9766         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9767         {
9768                 GL_BlendFunc(GL_ONE, GL_ONE);
9769                 GL_DepthMask(false);
9770         }
9771         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9772         {
9773                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9774                 GL_DepthMask(false);
9775         }
9776         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9777         {
9778                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9779                 GL_DepthMask(false);
9780         }
9781         else
9782         {
9783                 GL_BlendFunc(GL_ONE, GL_ZERO);
9784                 GL_DepthMask(writedepth);
9785         }
9786
9787         if (r_showsurfaces.integer == 3)
9788         {
9789                 rsurface.passcolor4f = NULL;
9790
9791                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9792                 {
9793                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9794
9795                         rsurface.passcolor4f = NULL;
9796                         rsurface.passcolor4f_vertexbuffer = 0;
9797                         rsurface.passcolor4f_bufferoffset = 0;
9798                 }
9799                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9800                 {
9801                         qboolean applycolor = true;
9802                         float one = 1.0;
9803
9804                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9805
9806                         r_refdef.lightmapintensity = 1;
9807                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9808                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9809                 }
9810                 else if (FAKELIGHT_ENABLED)
9811                 {
9812                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9813
9814                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
9815                         RSurf_DrawBatch_GL11_ApplyFakeLight();
9816                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9817                 }
9818                 else
9819                 {
9820                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9821
9822                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9823                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9824                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9825                 }
9826
9827                 if(!rsurface.passcolor4f)
9828                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9829
9830                 RSurf_DrawBatch_GL11_ApplyAmbient();
9831                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9832                 if(r_refdef.fogenabled)
9833                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9834                 RSurf_DrawBatch_GL11_ClampColor();
9835
9836                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9837                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9838                 RSurf_DrawBatch();
9839         }
9840         else if (!r_refdef.view.showdebug)
9841         {
9842                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9843                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9844                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9845                 {
9846                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9847                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9848                 }
9849                 R_Mesh_PrepareVertices_Generic_Unlock();
9850                 RSurf_DrawBatch();
9851         }
9852         else if (r_showsurfaces.integer == 4)
9853         {
9854                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9855                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9856                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9857                 {
9858                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
9859                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9860                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9861                 }
9862                 R_Mesh_PrepareVertices_Generic_Unlock();
9863                 RSurf_DrawBatch();
9864         }
9865         else if (r_showsurfaces.integer == 2)
9866         {
9867                 const int *e;
9868                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9869                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9870                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9871                 {
9872                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9873                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9874                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9875                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9876                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9877                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9878                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9879                 }
9880                 R_Mesh_PrepareVertices_Generic_Unlock();
9881                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9882         }
9883         else
9884         {
9885                 int texturesurfaceindex;
9886                 int k;
9887                 const msurface_t *surface;
9888                 float surfacecolor4f[4];
9889                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9890                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9891                 vi = 0;
9892                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9893                 {
9894                         surface = texturesurfacelist[texturesurfaceindex];
9895                         k = (int)(((size_t)surface) / sizeof(msurface_t));
9896                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9897                         for (j = 0;j < surface->num_vertices;j++)
9898                         {
9899                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9900                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9901                                 vi++;
9902                         }
9903                 }
9904                 R_Mesh_PrepareVertices_Generic_Unlock();
9905                 RSurf_DrawBatch();
9906         }
9907 }
9908
9909 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9910 {
9911         CHECKGLERROR
9912         RSurf_SetupDepthAndCulling();
9913         if (r_showsurfaces.integer)
9914         {
9915                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9916                 return;
9917         }
9918         switch (vid.renderpath)
9919         {
9920         case RENDERPATH_GL20:
9921         case RENDERPATH_D3D9:
9922         case RENDERPATH_D3D10:
9923         case RENDERPATH_D3D11:
9924         case RENDERPATH_SOFT:
9925         case RENDERPATH_GLES2:
9926                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9927                 break;
9928         case RENDERPATH_GL13:
9929         case RENDERPATH_GLES1:
9930                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9931                 break;
9932         case RENDERPATH_GL11:
9933                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9934                 break;
9935         }
9936         CHECKGLERROR
9937 }
9938
9939 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9940 {
9941         CHECKGLERROR
9942         RSurf_SetupDepthAndCulling();
9943         if (r_showsurfaces.integer)
9944         {
9945                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9946                 return;
9947         }
9948         switch (vid.renderpath)
9949         {
9950         case RENDERPATH_GL20:
9951         case RENDERPATH_D3D9:
9952         case RENDERPATH_D3D10:
9953         case RENDERPATH_D3D11:
9954         case RENDERPATH_SOFT:
9955         case RENDERPATH_GLES2:
9956                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9957                 break;
9958         case RENDERPATH_GL13:
9959         case RENDERPATH_GLES1:
9960                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9961                 break;
9962         case RENDERPATH_GL11:
9963                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9964                 break;
9965         }
9966         CHECKGLERROR
9967 }
9968
9969 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9970 {
9971         int i, j;
9972         int texturenumsurfaces, endsurface;
9973         texture_t *texture;
9974         const msurface_t *surface;
9975         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9976
9977         // if the model is static it doesn't matter what value we give for
9978         // wantnormals and wanttangents, so this logic uses only rules applicable
9979         // to a model, knowing that they are meaningless otherwise
9980         if (ent == r_refdef.scene.worldentity)
9981                 RSurf_ActiveWorldEntity();
9982         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9983                 RSurf_ActiveModelEntity(ent, false, false, false);
9984         else
9985         {
9986                 switch (vid.renderpath)
9987                 {
9988                 case RENDERPATH_GL20:
9989                 case RENDERPATH_D3D9:
9990                 case RENDERPATH_D3D10:
9991                 case RENDERPATH_D3D11:
9992                 case RENDERPATH_SOFT:
9993                 case RENDERPATH_GLES2:
9994                         RSurf_ActiveModelEntity(ent, true, true, false);
9995                         break;
9996                 case RENDERPATH_GL11:
9997                 case RENDERPATH_GL13:
9998                 case RENDERPATH_GLES1:
9999                         RSurf_ActiveModelEntity(ent, true, false, false);
10000                         break;
10001                 }
10002         }
10003
10004         if (r_transparentdepthmasking.integer)
10005         {
10006                 qboolean setup = false;
10007                 for (i = 0;i < numsurfaces;i = j)
10008                 {
10009                         j = i + 1;
10010                         surface = rsurface.modelsurfaces + surfacelist[i];
10011                         texture = surface->texture;
10012                         rsurface.texture = R_GetCurrentTexture(texture);
10013                         rsurface.lightmaptexture = NULL;
10014                         rsurface.deluxemaptexture = NULL;
10015                         rsurface.uselightmaptexture = false;
10016                         // scan ahead until we find a different texture
10017                         endsurface = min(i + 1024, numsurfaces);
10018                         texturenumsurfaces = 0;
10019                         texturesurfacelist[texturenumsurfaces++] = surface;
10020                         for (;j < endsurface;j++)
10021                         {
10022                                 surface = rsurface.modelsurfaces + surfacelist[j];
10023                                 if (texture != surface->texture)
10024                                         break;
10025                                 texturesurfacelist[texturenumsurfaces++] = surface;
10026                         }
10027                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10028                                 continue;
10029                         // render the range of surfaces as depth
10030                         if (!setup)
10031                         {
10032                                 setup = true;
10033                                 GL_ColorMask(0,0,0,0);
10034                                 GL_Color(1,1,1,1);
10035                                 GL_DepthTest(true);
10036                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10037                                 GL_DepthMask(true);
10038 //                              R_Mesh_ResetTextureState();
10039                                 R_SetupShader_DepthOrShadow();
10040                         }
10041                         RSurf_SetupDepthAndCulling();
10042                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10043                         if (rsurface.batchvertex3fbuffer)
10044                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10045                         else
10046                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10047                         RSurf_DrawBatch();
10048                 }
10049                 if (setup)
10050                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10051         }
10052
10053         for (i = 0;i < numsurfaces;i = j)
10054         {
10055                 j = i + 1;
10056                 surface = rsurface.modelsurfaces + surfacelist[i];
10057                 texture = surface->texture;
10058                 rsurface.texture = R_GetCurrentTexture(texture);
10059                 // scan ahead until we find a different texture
10060                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10061                 texturenumsurfaces = 0;
10062                 texturesurfacelist[texturenumsurfaces++] = surface;
10063                 if(FAKELIGHT_ENABLED)
10064                 {
10065                         rsurface.lightmaptexture = NULL;
10066                         rsurface.deluxemaptexture = NULL;
10067                         rsurface.uselightmaptexture = false;
10068                         for (;j < endsurface;j++)
10069                         {
10070                                 surface = rsurface.modelsurfaces + surfacelist[j];
10071                                 if (texture != surface->texture)
10072                                         break;
10073                                 texturesurfacelist[texturenumsurfaces++] = surface;
10074                         }
10075                 }
10076                 else
10077                 {
10078                         rsurface.lightmaptexture = surface->lightmaptexture;
10079                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10080                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10081                         for (;j < endsurface;j++)
10082                         {
10083                                 surface = rsurface.modelsurfaces + surfacelist[j];
10084                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10085                                         break;
10086                                 texturesurfacelist[texturenumsurfaces++] = surface;
10087                         }
10088                 }
10089                 // render the range of surfaces
10090                 if (ent == r_refdef.scene.worldentity)
10091                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10092                 else
10093                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10094         }
10095         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10096 }
10097
10098 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10099 {
10100         // transparent surfaces get pushed off into the transparent queue
10101         int surfacelistindex;
10102         const msurface_t *surface;
10103         vec3_t tempcenter, center;
10104         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10105         {
10106                 surface = texturesurfacelist[surfacelistindex];
10107                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10108                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10109                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10110                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10111                 if (queueentity->transparent_offset) // transparent offset
10112                 {
10113                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10114                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10115                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10116                 }
10117                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10118         }
10119 }
10120
10121 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10122 {
10123         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10124                 return;
10125         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10126                 return;
10127         RSurf_SetupDepthAndCulling();
10128         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10129         if (rsurface.batchvertex3fbuffer)
10130                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10131         else
10132                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10133         RSurf_DrawBatch();
10134 }
10135
10136 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10137 {
10138         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10139         CHECKGLERROR
10140         if (depthonly)
10141                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10142         else if (prepass)
10143         {
10144                 if (!rsurface.texture->currentnumlayers)
10145                         return;
10146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10147                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10148                 else
10149                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10150         }
10151         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10152                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10153         else if (!rsurface.texture->currentnumlayers)
10154                 return;
10155         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10156         {
10157                 // in the deferred case, transparent surfaces were queued during prepass
10158                 if (!r_shadow_usingdeferredprepass)
10159                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10160         }
10161         else
10162         {
10163                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10164                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10165         }
10166         CHECKGLERROR
10167 }
10168
10169 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10170 {
10171         int i, j;
10172         texture_t *texture;
10173         R_FrameData_SetMark();
10174         // break the surface list down into batches by texture and use of lightmapping
10175         for (i = 0;i < numsurfaces;i = j)
10176         {
10177                 j = i + 1;
10178                 // texture is the base texture pointer, rsurface.texture is the
10179                 // current frame/skin the texture is directing us to use (for example
10180                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10181                 // use skin 1 instead)
10182                 texture = surfacelist[i]->texture;
10183                 rsurface.texture = R_GetCurrentTexture(texture);
10184                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10185                 {
10186                         // if this texture is not the kind we want, skip ahead to the next one
10187                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10188                                 ;
10189                         continue;
10190                 }
10191                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10192                 {
10193                         rsurface.lightmaptexture = NULL;
10194                         rsurface.deluxemaptexture = NULL;
10195                         rsurface.uselightmaptexture = false;
10196                         // simply scan ahead until we find a different texture or lightmap state
10197                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10198                                 ;
10199                 }
10200                 else
10201                 {
10202                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10203                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10204                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10205                         // simply scan ahead until we find a different texture or lightmap state
10206                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10207                                 ;
10208                 }
10209                 // render the range of surfaces
10210                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10211         }
10212         R_FrameData_ReturnToMark();
10213 }
10214
10215 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10216 {
10217         CHECKGLERROR
10218         if (depthonly)
10219                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10220         else if (prepass)
10221         {
10222                 if (!rsurface.texture->currentnumlayers)
10223                         return;
10224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10225                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10226                 else
10227                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10228         }
10229         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10230                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10231         else if (!rsurface.texture->currentnumlayers)
10232                 return;
10233         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10234         {
10235                 // in the deferred case, transparent surfaces were queued during prepass
10236                 if (!r_shadow_usingdeferredprepass)
10237                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10238         }
10239         else
10240         {
10241                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10242                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10243         }
10244         CHECKGLERROR
10245 }
10246
10247 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10248 {
10249         int i, j;
10250         texture_t *texture;
10251         R_FrameData_SetMark();
10252         // break the surface list down into batches by texture and use of lightmapping
10253         for (i = 0;i < numsurfaces;i = j)
10254         {
10255                 j = i + 1;
10256                 // texture is the base texture pointer, rsurface.texture is the
10257                 // current frame/skin the texture is directing us to use (for example
10258                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10259                 // use skin 1 instead)
10260                 texture = surfacelist[i]->texture;
10261                 rsurface.texture = R_GetCurrentTexture(texture);
10262                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10263                 {
10264                         // if this texture is not the kind we want, skip ahead to the next one
10265                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10266                                 ;
10267                         continue;
10268                 }
10269                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10270                 {
10271                         rsurface.lightmaptexture = NULL;
10272                         rsurface.deluxemaptexture = NULL;
10273                         rsurface.uselightmaptexture = false;
10274                         // simply scan ahead until we find a different texture or lightmap state
10275                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10276                                 ;
10277                 }
10278                 else
10279                 {
10280                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10281                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10282                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10283                         // simply scan ahead until we find a different texture or lightmap state
10284                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10285                                 ;
10286                 }
10287                 // render the range of surfaces
10288                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10289         }
10290         R_FrameData_ReturnToMark();
10291 }
10292
10293 float locboxvertex3f[6*4*3] =
10294 {
10295         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10296         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10297         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10298         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10299         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10300         1,0,0, 0,0,0, 0,1,0, 1,1,0
10301 };
10302
10303 unsigned short locboxelements[6*2*3] =
10304 {
10305          0, 1, 2, 0, 2, 3,
10306          4, 5, 6, 4, 6, 7,
10307          8, 9,10, 8,10,11,
10308         12,13,14, 12,14,15,
10309         16,17,18, 16,18,19,
10310         20,21,22, 20,22,23
10311 };
10312
10313 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10314 {
10315         int i, j;
10316         cl_locnode_t *loc = (cl_locnode_t *)ent;
10317         vec3_t mins, size;
10318         float vertex3f[6*4*3];
10319         CHECKGLERROR
10320         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10321         GL_DepthMask(false);
10322         GL_DepthRange(0, 1);
10323         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10324         GL_DepthTest(true);
10325         GL_CullFace(GL_NONE);
10326         R_EntityMatrix(&identitymatrix);
10327
10328 //      R_Mesh_ResetTextureState();
10329
10330         i = surfacelist[0];
10331         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10332                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10333                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10334                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10335
10336         if (VectorCompare(loc->mins, loc->maxs))
10337         {
10338                 VectorSet(size, 2, 2, 2);
10339                 VectorMA(loc->mins, -0.5f, size, mins);
10340         }
10341         else
10342         {
10343                 VectorCopy(loc->mins, mins);
10344                 VectorSubtract(loc->maxs, loc->mins, size);
10345         }
10346
10347         for (i = 0;i < 6*4*3;)
10348                 for (j = 0;j < 3;j++, i++)
10349                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10350
10351         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10352         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10353         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10354 }
10355
10356 void R_DrawLocs(void)
10357 {
10358         int index;
10359         cl_locnode_t *loc, *nearestloc;
10360         vec3_t center;
10361         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10362         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10363         {
10364                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10365                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10366         }
10367 }
10368
10369 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10370 {
10371         if (decalsystem->decals)
10372                 Mem_Free(decalsystem->decals);
10373         memset(decalsystem, 0, sizeof(*decalsystem));
10374 }
10375
10376 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)
10377 {
10378         tridecal_t *decal;
10379         tridecal_t *decals;
10380         int i;
10381
10382         // expand or initialize the system
10383         if (decalsystem->maxdecals <= decalsystem->numdecals)
10384         {
10385                 decalsystem_t old = *decalsystem;
10386                 qboolean useshortelements;
10387                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10388                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10389                 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)));
10390                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10391                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10392                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10393                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10394                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10395                 if (decalsystem->numdecals)
10396                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10397                 if (old.decals)
10398                         Mem_Free(old.decals);
10399                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10400                         decalsystem->element3i[i] = i;
10401                 if (useshortelements)
10402                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10403                                 decalsystem->element3s[i] = i;
10404         }
10405
10406         // grab a decal and search for another free slot for the next one
10407         decals = decalsystem->decals;
10408         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10409         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10410                 ;
10411         decalsystem->freedecal = i;
10412         if (decalsystem->numdecals <= i)
10413                 decalsystem->numdecals = i + 1;
10414
10415         // initialize the decal
10416         decal->lived = 0;
10417         decal->triangleindex = triangleindex;
10418         decal->surfaceindex = surfaceindex;
10419         decal->decalsequence = decalsequence;
10420         decal->color4f[0][0] = c0[0];
10421         decal->color4f[0][1] = c0[1];
10422         decal->color4f[0][2] = c0[2];
10423         decal->color4f[0][3] = 1;
10424         decal->color4f[1][0] = c1[0];
10425         decal->color4f[1][1] = c1[1];
10426         decal->color4f[1][2] = c1[2];
10427         decal->color4f[1][3] = 1;
10428         decal->color4f[2][0] = c2[0];
10429         decal->color4f[2][1] = c2[1];
10430         decal->color4f[2][2] = c2[2];
10431         decal->color4f[2][3] = 1;
10432         decal->vertex3f[0][0] = v0[0];
10433         decal->vertex3f[0][1] = v0[1];
10434         decal->vertex3f[0][2] = v0[2];
10435         decal->vertex3f[1][0] = v1[0];
10436         decal->vertex3f[1][1] = v1[1];
10437         decal->vertex3f[1][2] = v1[2];
10438         decal->vertex3f[2][0] = v2[0];
10439         decal->vertex3f[2][1] = v2[1];
10440         decal->vertex3f[2][2] = v2[2];
10441         decal->texcoord2f[0][0] = t0[0];
10442         decal->texcoord2f[0][1] = t0[1];
10443         decal->texcoord2f[1][0] = t1[0];
10444         decal->texcoord2f[1][1] = t1[1];
10445         decal->texcoord2f[2][0] = t2[0];
10446         decal->texcoord2f[2][1] = t2[1];
10447         TriangleNormal(v0, v1, v2, decal->plane);
10448         VectorNormalize(decal->plane);
10449         decal->plane[3] = DotProduct(v0, decal->plane);
10450 }
10451
10452 extern cvar_t cl_decals_bias;
10453 extern cvar_t cl_decals_models;
10454 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10455 // baseparms, parms, temps
10456 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)
10457 {
10458         int cornerindex;
10459         int index;
10460         float v[9][3];
10461         const float *vertex3f;
10462         const float *normal3f;
10463         int numpoints;
10464         float points[2][9][3];
10465         float temp[3];
10466         float tc[9][2];
10467         float f;
10468         float c[9][4];
10469         const int *e;
10470
10471         e = rsurface.modelelement3i + 3*triangleindex;
10472
10473         vertex3f = rsurface.modelvertex3f;
10474         normal3f = rsurface.modelnormal3f;
10475
10476         if (normal3f)
10477         {
10478                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10479                 {
10480                         index = 3*e[cornerindex];
10481                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10482                 }
10483         }
10484         else
10485         {
10486                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10487                 {
10488                         index = 3*e[cornerindex];
10489                         VectorCopy(vertex3f + index, v[cornerindex]);
10490                 }
10491         }
10492
10493         // cull backfaces
10494         //TriangleNormal(v[0], v[1], v[2], normal);
10495         //if (DotProduct(normal, localnormal) < 0.0f)
10496         //      continue;
10497         // clip by each of the box planes formed from the projection matrix
10498         // if anything survives, we emit the decal
10499         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]);
10500         if (numpoints < 3)
10501                 return;
10502         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]);
10503         if (numpoints < 3)
10504                 return;
10505         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]);
10506         if (numpoints < 3)
10507                 return;
10508         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]);
10509         if (numpoints < 3)
10510                 return;
10511         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]);
10512         if (numpoints < 3)
10513                 return;
10514         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]);
10515         if (numpoints < 3)
10516                 return;
10517         // some part of the triangle survived, so we have to accept it...
10518         if (dynamic)
10519         {
10520                 // dynamic always uses the original triangle
10521                 numpoints = 3;
10522                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10523                 {
10524                         index = 3*e[cornerindex];
10525                         VectorCopy(vertex3f + index, v[cornerindex]);
10526                 }
10527         }
10528         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10529         {
10530                 // convert vertex positions to texcoords
10531                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10532                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10533                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10534                 // calculate distance fade from the projection origin
10535                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10536                 f = bound(0.0f, f, 1.0f);
10537                 c[cornerindex][0] = r * f;
10538                 c[cornerindex][1] = g * f;
10539                 c[cornerindex][2] = b * f;
10540                 c[cornerindex][3] = 1.0f;
10541                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10542         }
10543         if (dynamic)
10544                 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);
10545         else
10546                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10547                         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);
10548 }
10549 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)
10550 {
10551         matrix4x4_t projection;
10552         decalsystem_t *decalsystem;
10553         qboolean dynamic;
10554         dp_model_t *model;
10555         const msurface_t *surface;
10556         const msurface_t *surfaces;
10557         const int *surfacelist;
10558         const texture_t *texture;
10559         int numtriangles;
10560         int numsurfacelist;
10561         int surfacelistindex;
10562         int surfaceindex;
10563         int triangleindex;
10564         float localorigin[3];
10565         float localnormal[3];
10566         float localmins[3];
10567         float localmaxs[3];
10568         float localsize;
10569         //float normal[3];
10570         float planes[6][4];
10571         float angles[3];
10572         bih_t *bih;
10573         int bih_triangles_count;
10574         int bih_triangles[256];
10575         int bih_surfaces[256];
10576
10577         decalsystem = &ent->decalsystem;
10578         model = ent->model;
10579         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10580         {
10581                 R_DecalSystem_Reset(&ent->decalsystem);
10582                 return;
10583         }
10584
10585         if (!model->brush.data_leafs && !cl_decals_models.integer)
10586         {
10587                 if (decalsystem->model)
10588                         R_DecalSystem_Reset(decalsystem);
10589                 return;
10590         }
10591
10592         if (decalsystem->model != model)
10593                 R_DecalSystem_Reset(decalsystem);
10594         decalsystem->model = model;
10595
10596         RSurf_ActiveModelEntity(ent, true, false, false);
10597
10598         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10599         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10600         VectorNormalize(localnormal);
10601         localsize = worldsize*rsurface.inversematrixscale;
10602         localmins[0] = localorigin[0] - localsize;
10603         localmins[1] = localorigin[1] - localsize;
10604         localmins[2] = localorigin[2] - localsize;
10605         localmaxs[0] = localorigin[0] + localsize;
10606         localmaxs[1] = localorigin[1] + localsize;
10607         localmaxs[2] = localorigin[2] + localsize;
10608
10609         //VectorCopy(localnormal, planes[4]);
10610         //VectorVectors(planes[4], planes[2], planes[0]);
10611         AnglesFromVectors(angles, localnormal, NULL, false);
10612         AngleVectors(angles, planes[0], planes[2], planes[4]);
10613         VectorNegate(planes[0], planes[1]);
10614         VectorNegate(planes[2], planes[3]);
10615         VectorNegate(planes[4], planes[5]);
10616         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10617         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10618         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10619         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10620         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10621         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10622
10623 #if 1
10624 // works
10625 {
10626         matrix4x4_t forwardprojection;
10627         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10628         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10629 }
10630 #else
10631 // broken
10632 {
10633         float projectionvector[4][3];
10634         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10635         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10636         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10637         projectionvector[0][0] = planes[0][0] * ilocalsize;
10638         projectionvector[0][1] = planes[1][0] * ilocalsize;
10639         projectionvector[0][2] = planes[2][0] * ilocalsize;
10640         projectionvector[1][0] = planes[0][1] * ilocalsize;
10641         projectionvector[1][1] = planes[1][1] * ilocalsize;
10642         projectionvector[1][2] = planes[2][1] * ilocalsize;
10643         projectionvector[2][0] = planes[0][2] * ilocalsize;
10644         projectionvector[2][1] = planes[1][2] * ilocalsize;
10645         projectionvector[2][2] = planes[2][2] * ilocalsize;
10646         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10647         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10648         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10649         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10650 }
10651 #endif
10652
10653         dynamic = model->surfmesh.isanimated;
10654         numsurfacelist = model->nummodelsurfaces;
10655         surfacelist = model->sortedmodelsurfaces;
10656         surfaces = model->data_surfaces;
10657
10658         bih = NULL;
10659         bih_triangles_count = -1;
10660         if(!dynamic)
10661         {
10662                 if(model->render_bih.numleafs)
10663                         bih = &model->render_bih;
10664                 else if(model->collision_bih.numleafs)
10665                         bih = &model->collision_bih;
10666         }
10667         if(bih)
10668                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10669         if(bih_triangles_count == 0)
10670                 return;
10671         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10672                 return;
10673         if(bih_triangles_count > 0)
10674         {
10675                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10676                 {
10677                         surfaceindex = bih_surfaces[triangleindex];
10678                         surface = surfaces + surfaceindex;
10679                         texture = surface->texture;
10680                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10681                                 continue;
10682                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10683                                 continue;
10684                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10685                 }
10686         }
10687         else
10688         {
10689                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10690                 {
10691                         surfaceindex = surfacelist[surfacelistindex];
10692                         surface = surfaces + surfaceindex;
10693                         // check cull box first because it rejects more than any other check
10694                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10695                                 continue;
10696                         // skip transparent surfaces
10697                         texture = surface->texture;
10698                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10699                                 continue;
10700                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10701                                 continue;
10702                         numtriangles = surface->num_triangles;
10703                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10704                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10705                 }
10706         }
10707 }
10708
10709 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10710 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)
10711 {
10712         int renderentityindex;
10713         float worldmins[3];
10714         float worldmaxs[3];
10715         entity_render_t *ent;
10716
10717         if (!cl_decals_newsystem.integer)
10718                 return;
10719
10720         worldmins[0] = worldorigin[0] - worldsize;
10721         worldmins[1] = worldorigin[1] - worldsize;
10722         worldmins[2] = worldorigin[2] - worldsize;
10723         worldmaxs[0] = worldorigin[0] + worldsize;
10724         worldmaxs[1] = worldorigin[1] + worldsize;
10725         worldmaxs[2] = worldorigin[2] + worldsize;
10726
10727         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10728
10729         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10730         {
10731                 ent = r_refdef.scene.entities[renderentityindex];
10732                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10733                         continue;
10734
10735                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10736         }
10737 }
10738
10739 typedef struct r_decalsystem_splatqueue_s
10740 {
10741         vec3_t worldorigin;
10742         vec3_t worldnormal;
10743         float color[4];
10744         float tcrange[4];
10745         float worldsize;
10746         int decalsequence;
10747 }
10748 r_decalsystem_splatqueue_t;
10749
10750 int r_decalsystem_numqueued = 0;
10751 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10752
10753 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)
10754 {
10755         r_decalsystem_splatqueue_t *queue;
10756
10757         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10758                 return;
10759
10760         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10761         VectorCopy(worldorigin, queue->worldorigin);
10762         VectorCopy(worldnormal, queue->worldnormal);
10763         Vector4Set(queue->color, r, g, b, a);
10764         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10765         queue->worldsize = worldsize;
10766         queue->decalsequence = cl.decalsequence++;
10767 }
10768
10769 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10770 {
10771         int i;
10772         r_decalsystem_splatqueue_t *queue;
10773
10774         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10775                 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);
10776         r_decalsystem_numqueued = 0;
10777 }
10778
10779 extern cvar_t cl_decals_max;
10780 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10781 {
10782         int i;
10783         decalsystem_t *decalsystem = &ent->decalsystem;
10784         int numdecals;
10785         int killsequence;
10786         tridecal_t *decal;
10787         float frametime;
10788         float lifetime;
10789
10790         if (!decalsystem->numdecals)
10791                 return;
10792
10793         if (r_showsurfaces.integer)
10794                 return;
10795
10796         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10797         {
10798                 R_DecalSystem_Reset(decalsystem);
10799                 return;
10800         }
10801
10802         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10803         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10804
10805         if (decalsystem->lastupdatetime)
10806                 frametime = (cl.time - decalsystem->lastupdatetime);
10807         else
10808                 frametime = 0;
10809         decalsystem->lastupdatetime = cl.time;
10810         decal = decalsystem->decals;
10811         numdecals = decalsystem->numdecals;
10812
10813         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10814         {
10815                 if (decal->color4f[0][3])
10816                 {
10817                         decal->lived += frametime;
10818                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10819                         {
10820                                 memset(decal, 0, sizeof(*decal));
10821                                 if (decalsystem->freedecal > i)
10822                                         decalsystem->freedecal = i;
10823                         }
10824                 }
10825         }
10826         decal = decalsystem->decals;
10827         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10828                 numdecals--;
10829
10830         // collapse the array by shuffling the tail decals into the gaps
10831         for (;;)
10832         {
10833                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10834                         decalsystem->freedecal++;
10835                 if (decalsystem->freedecal == numdecals)
10836                         break;
10837                 decal[decalsystem->freedecal] = decal[--numdecals];
10838         }
10839
10840         decalsystem->numdecals = numdecals;
10841
10842         if (numdecals <= 0)
10843         {
10844                 // if there are no decals left, reset decalsystem
10845                 R_DecalSystem_Reset(decalsystem);
10846         }
10847 }
10848
10849 extern skinframe_t *decalskinframe;
10850 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10851 {
10852         int i;
10853         decalsystem_t *decalsystem = &ent->decalsystem;
10854         int numdecals;
10855         tridecal_t *decal;
10856         float faderate;
10857         float alpha;
10858         float *v3f;
10859         float *c4f;
10860         float *t2f;
10861         const int *e;
10862         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10863         int numtris = 0;
10864
10865         numdecals = decalsystem->numdecals;
10866         if (!numdecals)
10867                 return;
10868
10869         if (r_showsurfaces.integer)
10870                 return;
10871
10872         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10873         {
10874                 R_DecalSystem_Reset(decalsystem);
10875                 return;
10876         }
10877
10878         // if the model is static it doesn't matter what value we give for
10879         // wantnormals and wanttangents, so this logic uses only rules applicable
10880         // to a model, knowing that they are meaningless otherwise
10881         if (ent == r_refdef.scene.worldentity)
10882                 RSurf_ActiveWorldEntity();
10883         else
10884                 RSurf_ActiveModelEntity(ent, false, false, false);
10885
10886         decalsystem->lastupdatetime = cl.time;
10887         decal = decalsystem->decals;
10888
10889         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10890
10891         // update vertex positions for animated models
10892         v3f = decalsystem->vertex3f;
10893         c4f = decalsystem->color4f;
10894         t2f = decalsystem->texcoord2f;
10895         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10896         {
10897                 if (!decal->color4f[0][3])
10898                         continue;
10899
10900                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10901                         continue;
10902
10903                 // skip backfaces
10904                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10905                         continue;
10906
10907                 // update color values for fading decals
10908                 if (decal->lived >= cl_decals_time.value)
10909                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10910                 else
10911                         alpha = 1.0f;
10912
10913                 c4f[ 0] = decal->color4f[0][0] * alpha;
10914                 c4f[ 1] = decal->color4f[0][1] * alpha;
10915                 c4f[ 2] = decal->color4f[0][2] * alpha;
10916                 c4f[ 3] = 1;
10917                 c4f[ 4] = decal->color4f[1][0] * alpha;
10918                 c4f[ 5] = decal->color4f[1][1] * alpha;
10919                 c4f[ 6] = decal->color4f[1][2] * alpha;
10920                 c4f[ 7] = 1;
10921                 c4f[ 8] = decal->color4f[2][0] * alpha;
10922                 c4f[ 9] = decal->color4f[2][1] * alpha;
10923                 c4f[10] = decal->color4f[2][2] * alpha;
10924                 c4f[11] = 1;
10925
10926                 t2f[0] = decal->texcoord2f[0][0];
10927                 t2f[1] = decal->texcoord2f[0][1];
10928                 t2f[2] = decal->texcoord2f[1][0];
10929                 t2f[3] = decal->texcoord2f[1][1];
10930                 t2f[4] = decal->texcoord2f[2][0];
10931                 t2f[5] = decal->texcoord2f[2][1];
10932
10933                 // update vertex positions for animated models
10934                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10935                 {
10936                         e = rsurface.modelelement3i + 3*decal->triangleindex;
10937                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10938                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10939                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10940                 }
10941                 else
10942                 {
10943                         VectorCopy(decal->vertex3f[0], v3f);
10944                         VectorCopy(decal->vertex3f[1], v3f + 3);
10945                         VectorCopy(decal->vertex3f[2], v3f + 6);
10946                 }
10947
10948                 if (r_refdef.fogenabled)
10949                 {
10950                         alpha = RSurf_FogVertex(v3f);
10951                         VectorScale(c4f, alpha, c4f);
10952                         alpha = RSurf_FogVertex(v3f + 3);
10953                         VectorScale(c4f + 4, alpha, c4f + 4);
10954                         alpha = RSurf_FogVertex(v3f + 6);
10955                         VectorScale(c4f + 8, alpha, c4f + 8);
10956                 }
10957
10958                 v3f += 9;
10959                 c4f += 12;
10960                 t2f += 6;
10961                 numtris++;
10962         }
10963
10964         if (numtris > 0)
10965         {
10966                 r_refdef.stats.drawndecals += numtris;
10967
10968                 // now render the decals all at once
10969                 // (this assumes they all use one particle font texture!)
10970                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10971 //              R_Mesh_ResetTextureState();
10972                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10973                 GL_DepthMask(false);
10974                 GL_DepthRange(0, 1);
10975                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10976                 GL_DepthTest(true);
10977                 GL_CullFace(GL_NONE);
10978                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10979                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10980                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10981         }
10982 }
10983
10984 static void R_DrawModelDecals(void)
10985 {
10986         int i, numdecals;
10987
10988         // fade faster when there are too many decals
10989         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10990         for (i = 0;i < r_refdef.scene.numentities;i++)
10991                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10992
10993         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10994         for (i = 0;i < r_refdef.scene.numentities;i++)
10995                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10996                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10997
10998         R_DecalSystem_ApplySplatEntitiesQueue();
10999
11000         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11001         for (i = 0;i < r_refdef.scene.numentities;i++)
11002                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11003
11004         r_refdef.stats.totaldecals += numdecals;
11005
11006         if (r_showsurfaces.integer)
11007                 return;
11008
11009         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11010
11011         for (i = 0;i < r_refdef.scene.numentities;i++)
11012         {
11013                 if (!r_refdef.viewcache.entityvisible[i])
11014                         continue;
11015                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11016                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11017         }
11018 }
11019
11020 extern cvar_t mod_collision_bih;
11021 void R_DrawDebugModel(void)
11022 {
11023         entity_render_t *ent = rsurface.entity;
11024         int i, j, k, l, flagsmask;
11025         const msurface_t *surface;
11026         dp_model_t *model = ent->model;
11027         vec3_t v;
11028
11029         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11030                 return;
11031
11032         if (r_showoverdraw.value > 0)
11033         {
11034                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11035                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11036                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11037                 GL_DepthTest(false);
11038                 GL_DepthMask(false);
11039                 GL_DepthRange(0, 1);
11040                 GL_BlendFunc(GL_ONE, GL_ONE);
11041                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11042                 {
11043                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11044                                 continue;
11045                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11046                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11047                         {
11048                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11049                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11050                                 if (!rsurface.texture->currentlayers->depthmask)
11051                                         GL_Color(c, 0, 0, 1.0f);
11052                                 else if (ent == r_refdef.scene.worldentity)
11053                                         GL_Color(c, c, c, 1.0f);
11054                                 else
11055                                         GL_Color(0, c, 0, 1.0f);
11056                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11057                                 RSurf_DrawBatch();
11058                         }
11059                 }
11060                 rsurface.texture = NULL;
11061         }
11062
11063         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11064
11065 //      R_Mesh_ResetTextureState();
11066         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11067         GL_DepthRange(0, 1);
11068         GL_DepthTest(!r_showdisabledepthtest.integer);
11069         GL_DepthMask(false);
11070         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11071
11072         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11073         {
11074                 int triangleindex;
11075                 int bihleafindex;
11076                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11077                 const q3mbrush_t *brush;
11078                 const bih_t *bih = &model->collision_bih;
11079                 const bih_leaf_t *bihleaf;
11080                 float vertex3f[3][3];
11081                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11082                 cullbox = false;
11083                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11084                 {
11085                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11086                                 continue;
11087                         switch (bihleaf->type)
11088                         {
11089                         case BIH_BRUSH:
11090                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11091                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11092                                 {
11093                                         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);
11094                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11095                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11096                                 }
11097                                 break;
11098                         case BIH_COLLISIONTRIANGLE:
11099                                 triangleindex = bihleaf->itemindex;
11100                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11101                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11102                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11103                                 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);
11104                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11105                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11106                                 break;
11107                         case BIH_RENDERTRIANGLE:
11108                                 triangleindex = bihleaf->itemindex;
11109                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11110                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11111                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11112                                 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);
11113                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11114                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11115                                 break;
11116                         }
11117                 }
11118         }
11119
11120         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11121
11122         if (r_showtris.integer && qglPolygonMode)
11123         {
11124                 if (r_showdisabledepthtest.integer)
11125                 {
11126                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11127                         GL_DepthMask(false);
11128                 }
11129                 else
11130                 {
11131                         GL_BlendFunc(GL_ONE, GL_ZERO);
11132                         GL_DepthMask(true);
11133                 }
11134                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11135                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11136                 {
11137                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11138                                 continue;
11139                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11140                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11141                         {
11142                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11143                                 if (!rsurface.texture->currentlayers->depthmask)
11144                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11145                                 else if (ent == r_refdef.scene.worldentity)
11146                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11147                                 else
11148                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11149                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11150                                 RSurf_DrawBatch();
11151                         }
11152                 }
11153                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11154                 rsurface.texture = NULL;
11155         }
11156
11157         if (r_shownormals.value != 0 && qglBegin)
11158         {
11159                 if (r_showdisabledepthtest.integer)
11160                 {
11161                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11162                         GL_DepthMask(false);
11163                 }
11164                 else
11165                 {
11166                         GL_BlendFunc(GL_ONE, GL_ZERO);
11167                         GL_DepthMask(true);
11168                 }
11169                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11170                 {
11171                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11172                                 continue;
11173                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11174                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11175                         {
11176                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11177                                 qglBegin(GL_LINES);
11178                                 if (r_shownormals.value < 0)
11179                                 {
11180                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11181                                         {
11182                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11183                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11184                                                 qglVertex3f(v[0], v[1], v[2]);
11185                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11186                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11187                                                 qglVertex3f(v[0], v[1], v[2]);
11188                                         }
11189                                 }
11190                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11191                                 {
11192                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11193                                         {
11194                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11195                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11196                                                 qglVertex3f(v[0], v[1], v[2]);
11197                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11198                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11199                                                 qglVertex3f(v[0], v[1], v[2]);
11200                                         }
11201                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11202                                         {
11203                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11204                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11205                                                 qglVertex3f(v[0], v[1], v[2]);
11206                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11207                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11208                                                 qglVertex3f(v[0], v[1], v[2]);
11209                                         }
11210                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11211                                         {
11212                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11213                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11214                                                 qglVertex3f(v[0], v[1], v[2]);
11215                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11216                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11217                                                 qglVertex3f(v[0], v[1], v[2]);
11218                                         }
11219                                 }
11220                                 qglEnd();
11221                                 CHECKGLERROR
11222                         }
11223                 }
11224                 rsurface.texture = NULL;
11225         }
11226 }
11227
11228 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11229 int r_maxsurfacelist = 0;
11230 const msurface_t **r_surfacelist = NULL;
11231 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11232 {
11233         int i, j, endj, flagsmask;
11234         dp_model_t *model = r_refdef.scene.worldmodel;
11235         msurface_t *surfaces;
11236         unsigned char *update;
11237         int numsurfacelist = 0;
11238         if (model == NULL)
11239                 return;
11240
11241         if (r_maxsurfacelist < model->num_surfaces)
11242         {
11243                 r_maxsurfacelist = model->num_surfaces;
11244                 if (r_surfacelist)
11245                         Mem_Free((msurface_t**)r_surfacelist);
11246                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11247         }
11248
11249         RSurf_ActiveWorldEntity();
11250
11251         surfaces = model->data_surfaces;
11252         update = model->brushq1.lightmapupdateflags;
11253
11254         // update light styles on this submodel
11255         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11256         {
11257                 model_brush_lightstyleinfo_t *style;
11258                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11259                 {
11260                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11261                         {
11262                                 int *list = style->surfacelist;
11263                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11264                                 for (j = 0;j < style->numsurfaces;j++)
11265                                         update[list[j]] = true;
11266                         }
11267                 }
11268         }
11269
11270         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11271
11272         if (debug)
11273         {
11274                 R_DrawDebugModel();
11275                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11276                 return;
11277         }
11278
11279         rsurface.lightmaptexture = NULL;
11280         rsurface.deluxemaptexture = NULL;
11281         rsurface.uselightmaptexture = false;
11282         rsurface.texture = NULL;
11283         rsurface.rtlight = NULL;
11284         numsurfacelist = 0;
11285         // add visible surfaces to draw list
11286         for (i = 0;i < model->nummodelsurfaces;i++)
11287         {
11288                 j = model->sortedmodelsurfaces[i];
11289                 if (r_refdef.viewcache.world_surfacevisible[j])
11290                         r_surfacelist[numsurfacelist++] = surfaces + j;
11291         }
11292         // update lightmaps if needed
11293         if (model->brushq1.firstrender)
11294         {
11295                 model->brushq1.firstrender = false;
11296                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11297                         if (update[j])
11298                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11299         }
11300         else if (update)
11301         {
11302                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11303                         if (r_refdef.viewcache.world_surfacevisible[j])
11304                                 if (update[j])
11305                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11306         }
11307         // don't do anything if there were no surfaces
11308         if (!numsurfacelist)
11309         {
11310                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11311                 return;
11312         }
11313         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11314
11315         // add to stats if desired
11316         if (r_speeds.integer && !skysurfaces && !depthonly)
11317         {
11318                 r_refdef.stats.world_surfaces += numsurfacelist;
11319                 for (j = 0;j < numsurfacelist;j++)
11320                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11321         }
11322
11323         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11324 }
11325
11326 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11327 {
11328         int i, j, endj, flagsmask;
11329         dp_model_t *model = ent->model;
11330         msurface_t *surfaces;
11331         unsigned char *update;
11332         int numsurfacelist = 0;
11333         if (model == NULL)
11334                 return;
11335
11336         if (r_maxsurfacelist < model->num_surfaces)
11337         {
11338                 r_maxsurfacelist = model->num_surfaces;
11339                 if (r_surfacelist)
11340                         Mem_Free((msurface_t **)r_surfacelist);
11341                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11342         }
11343
11344         // if the model is static it doesn't matter what value we give for
11345         // wantnormals and wanttangents, so this logic uses only rules applicable
11346         // to a model, knowing that they are meaningless otherwise
11347         if (ent == r_refdef.scene.worldentity)
11348                 RSurf_ActiveWorldEntity();
11349         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11350                 RSurf_ActiveModelEntity(ent, false, false, false);
11351         else if (prepass)
11352                 RSurf_ActiveModelEntity(ent, true, true, true);
11353         else if (depthonly)
11354         {
11355                 switch (vid.renderpath)
11356                 {
11357                 case RENDERPATH_GL20:
11358                 case RENDERPATH_D3D9:
11359                 case RENDERPATH_D3D10:
11360                 case RENDERPATH_D3D11:
11361                 case RENDERPATH_SOFT:
11362                 case RENDERPATH_GLES2:
11363                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11364                         break;
11365                 case RENDERPATH_GL11:
11366                 case RENDERPATH_GL13:
11367                 case RENDERPATH_GLES1:
11368                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11369                         break;
11370                 }
11371         }
11372         else
11373         {
11374                 switch (vid.renderpath)
11375                 {
11376                 case RENDERPATH_GL20:
11377                 case RENDERPATH_D3D9:
11378                 case RENDERPATH_D3D10:
11379                 case RENDERPATH_D3D11:
11380                 case RENDERPATH_SOFT:
11381                 case RENDERPATH_GLES2:
11382                         RSurf_ActiveModelEntity(ent, true, true, false);
11383                         break;
11384                 case RENDERPATH_GL11:
11385                 case RENDERPATH_GL13:
11386                 case RENDERPATH_GLES1:
11387                         RSurf_ActiveModelEntity(ent, true, false, false);
11388                         break;
11389                 }
11390         }
11391
11392         surfaces = model->data_surfaces;
11393         update = model->brushq1.lightmapupdateflags;
11394
11395         // update light styles
11396         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11397         {
11398                 model_brush_lightstyleinfo_t *style;
11399                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11400                 {
11401                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11402                         {
11403                                 int *list = style->surfacelist;
11404                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11405                                 for (j = 0;j < style->numsurfaces;j++)
11406                                         update[list[j]] = true;
11407                         }
11408                 }
11409         }
11410
11411         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11412
11413         if (debug)
11414         {
11415                 R_DrawDebugModel();
11416                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11417                 return;
11418         }
11419
11420         rsurface.lightmaptexture = NULL;
11421         rsurface.deluxemaptexture = NULL;
11422         rsurface.uselightmaptexture = false;
11423         rsurface.texture = NULL;
11424         rsurface.rtlight = NULL;
11425         numsurfacelist = 0;
11426         // add visible surfaces to draw list
11427         for (i = 0;i < model->nummodelsurfaces;i++)
11428                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11429         // don't do anything if there were no surfaces
11430         if (!numsurfacelist)
11431         {
11432                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11433                 return;
11434         }
11435         // update lightmaps if needed
11436         if (update)
11437         {
11438                 int updated = 0;
11439                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11440                 {
11441                         if (update[j])
11442                         {
11443                                 updated++;
11444                                 R_BuildLightMap(ent, surfaces + j);
11445                         }
11446                 }
11447         }
11448         if (update)
11449                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11450                         if (update[j])
11451                                 R_BuildLightMap(ent, surfaces + j);
11452         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11453
11454         // add to stats if desired
11455         if (r_speeds.integer && !skysurfaces && !depthonly)
11456         {
11457                 r_refdef.stats.entities_surfaces += numsurfacelist;
11458                 for (j = 0;j < numsurfacelist;j++)
11459                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11460         }
11461
11462         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11463 }
11464
11465 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11466 {
11467         static texture_t texture;
11468         static msurface_t surface;
11469         const msurface_t *surfacelist = &surface;
11470
11471         // fake enough texture and surface state to render this geometry
11472
11473         texture.update_lastrenderframe = -1; // regenerate this texture
11474         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11475         texture.currentskinframe = skinframe;
11476         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11477         texture.offsetmapping = OFFSETMAPPING_OFF;
11478         texture.offsetscale = 1;
11479         texture.specularscalemod = 1;
11480         texture.specularpowermod = 1;
11481
11482         surface.texture = &texture;
11483         surface.num_triangles = numtriangles;
11484         surface.num_firsttriangle = firsttriangle;
11485         surface.num_vertices = numvertices;
11486         surface.num_firstvertex = firstvertex;
11487
11488         // now render it
11489         rsurface.texture = R_GetCurrentTexture(surface.texture);
11490         rsurface.lightmaptexture = NULL;
11491         rsurface.deluxemaptexture = NULL;
11492         rsurface.uselightmaptexture = false;
11493         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11494 }
11495
11496 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)
11497 {
11498         static msurface_t surface;
11499         const msurface_t *surfacelist = &surface;
11500
11501         // fake enough texture and surface state to render this geometry
11502         surface.texture = texture;
11503         surface.num_triangles = numtriangles;
11504         surface.num_firsttriangle = firsttriangle;
11505         surface.num_vertices = numvertices;
11506         surface.num_firstvertex = firstvertex;
11507
11508         // now render it
11509         rsurface.texture = R_GetCurrentTexture(surface.texture);
11510         rsurface.lightmaptexture = NULL;
11511         rsurface.deluxemaptexture = NULL;
11512         rsurface.uselightmaptexture = false;
11513         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11514 }